Add GIN support for pg_trgm. From Guillaume Smet <guillaume.smet@gmail.com>
with minor editorization by me. Hstore improvements * add operation hstore ? text - excat equivalent of exist() * remove undocumented behaviour of contains operation with NULL value * now 'key'::text=>NULL returns '"key"=>NULL' instead of NULL * Add GIN support for contains and exist operations * Add GiST support for exist operatiion * improve regression tests
This commit is contained in:
parent
15f91f2789
commit
754148d81f
@ -1,11 +1,11 @@
|
|||||||
# $PostgreSQL: pgsql/contrib/hstore/Makefile,v 1.4 2007/02/09 17:24:33 petere Exp $
|
# $PostgreSQL: pgsql/contrib/hstore/Makefile,v 1.5 2007/03/14 14:21:52 teodor Exp $
|
||||||
|
|
||||||
subdir = contrib/hstore
|
subdir = contrib/hstore
|
||||||
top_builddir = ../..
|
top_builddir = ../..
|
||||||
include $(top_builddir)/src/Makefile.global
|
include $(top_builddir)/src/Makefile.global
|
||||||
|
|
||||||
MODULE_big = hstore
|
MODULE_big = hstore
|
||||||
OBJS = hstore_io.o hstore_op.o hstore_gist.o crc32.o
|
OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o crc32.o
|
||||||
|
|
||||||
DATA_built = hstore.sql
|
DATA_built = hstore.sql
|
||||||
DATA = uninstall_hstore.sql
|
DATA = uninstall_hstore.sql
|
||||||
|
@ -117,13 +117,14 @@ regression=# select * from each('a=>1,b=>2');
|
|||||||
a | 1
|
a | 1
|
||||||
b | 2
|
b | 2
|
||||||
|
|
||||||
* exist (hstore,text) - returns 'true if key is exists in hstore and
|
* exist (hstore,text)
|
||||||
false otherwise.
|
* hstore ? text
|
||||||
|
- returns 'true if key is exists in hstore and false otherwise.
|
||||||
|
|
||||||
regression=# select exist('a=>1','a');
|
regression=# select exist('a=>1','a'), 'a=>1' ? 'a';
|
||||||
exist
|
exist | ?column?
|
||||||
----------
|
-------+----------
|
||||||
t
|
t | t
|
||||||
|
|
||||||
* defined (hstore,text) - returns true if key is exists in hstore and
|
* defined (hstore,text) - returns true if key is exists in hstore and
|
||||||
its value is not NULL.
|
its value is not NULL.
|
||||||
@ -135,9 +136,10 @@ regression=# select defined('a=>NULL','a');
|
|||||||
|
|
||||||
Indices
|
Indices
|
||||||
|
|
||||||
Module provides index support for '@>' and '<@' operations.
|
Module provides index support for '@>' and '?' operations.
|
||||||
|
|
||||||
create index hidx on testhstore using gist(h);
|
create index hidx on testhstore using gist(h);
|
||||||
|
create index hidx on testhstore using gin(h);
|
||||||
|
|
||||||
Note
|
Note
|
||||||
|
|
||||||
|
@ -998,3 +998,4 @@ auth=>BC, title=>CAC, subtitle=>BA, line=>997, date=>BAA
|
|||||||
wait=>AB, user=>ABC, line=>998, pos=>41, node=>CAC
|
wait=>AB, user=>ABC, line=>998, pos=>41, node=>CAC
|
||||||
state=>4, title=>AC, bad=>t, status=>59, line=>999, disabled=>t
|
state=>4, title=>AC, bad=>t, status=>59, line=>999, disabled=>t
|
||||||
user=>BC, line=>1000
|
user=>BC, line=>1000
|
||||||
|
wait=>NULL, line=>1000
|
||||||
|
@ -272,6 +272,12 @@ select ('aa=>NULL, c=>d , b=>16'::hstore->'aa') is null;
|
|||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select ('aa=>"NULL", c=>d , b=>16'::hstore->'aa') is null;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- exists/defined
|
-- exists/defined
|
||||||
select exist('a=>NULL, b=>qq', 'a');
|
select exist('a=>NULL, b=>qq', 'a');
|
||||||
exist
|
exist
|
||||||
@ -291,6 +297,12 @@ select exist('a=>NULL, b=>qq', 'c');
|
|||||||
f
|
f
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select exist('a=>"NULL", b=>qq', 'a');
|
||||||
|
exist
|
||||||
|
-------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
select defined('a=>NULL, b=>qq', 'a');
|
select defined('a=>NULL, b=>qq', 'a');
|
||||||
defined
|
defined
|
||||||
---------
|
---------
|
||||||
@ -309,6 +321,12 @@ select defined('a=>NULL, b=>qq', 'c');
|
|||||||
f
|
f
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select defined('a=>"NULL", b=>qq', 'a');
|
||||||
|
defined
|
||||||
|
---------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- delete
|
-- delete
|
||||||
select delete('a=>1 , b=>2, c=>3'::hstore, 'a');
|
select delete('a=>1 , b=>2, c=>3'::hstore, 'a');
|
||||||
delete
|
delete
|
||||||
@ -384,6 +402,18 @@ select 'a=>g, b=>c'::hstore || ( 'b'=>'gf' );
|
|||||||
"a"=>"g", "b"=>"gf"
|
"a"=>"g", "b"=>"gf"
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select 'a=>g, b=>c'::hstore || ( 'b'=>'NULL' );
|
||||||
|
?column?
|
||||||
|
-----------------------
|
||||||
|
"a"=>"g", "b"=>"NULL"
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select 'a=>g, b=>c'::hstore || ( 'b'=>NULL );
|
||||||
|
?column?
|
||||||
|
---------------------
|
||||||
|
"a"=>"g", "b"=>NULL
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- keys/values
|
-- keys/values
|
||||||
select akeys('aa=>1 , b=>2, cq=>3'::hstore || 'cq=>l, b=>g, fg=>f');
|
select akeys('aa=>1 , b=>2, cq=>3'::hstore || 'cq=>l, b=>g, fg=>f');
|
||||||
akeys
|
akeys
|
||||||
@ -485,19 +515,19 @@ select * from each('aaa=>bq, b=>NULL, ""=>1 ');
|
|||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- @>
|
-- @>
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, c=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>NULL';
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, g=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, g=>NULL';
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
f
|
f
|
||||||
@ -521,12 +551,6 @@ select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
|
|||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>NULL';
|
|
||||||
?column?
|
|
||||||
----------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>q';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>q';
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
@ -538,7 +562,7 @@ CREATE TABLE testhstore (h hstore);
|
|||||||
select count(*) from testhstore where h @> 'wait=>NULL';
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
189
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select count(*) from testhstore where h @> 'wait=>CC';
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
@ -553,12 +577,18 @@ select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
|||||||
2
|
2
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
194
|
||||||
|
(1 row)
|
||||||
|
|
||||||
create index hidx on testhstore using gist(h);
|
create index hidx on testhstore using gist(h);
|
||||||
set enable_seqscan=off;
|
set enable_seqscan=off;
|
||||||
select count(*) from testhstore where h @> 'wait=>NULL';
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
189
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select count(*) from testhstore where h @> 'wait=>CC';
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
@ -573,16 +603,49 @@ select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
|||||||
2
|
2
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
194
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop index hidx;
|
||||||
|
create index hidx on testhstore using gin (h);
|
||||||
|
set enable_seqscan=off;
|
||||||
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
15
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
194
|
||||||
|
(1 row)
|
||||||
|
|
||||||
select count(*) from (select (each(h)).key from testhstore) as wow ;
|
select count(*) from (select (each(h)).key from testhstore) as wow ;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
4779
|
4781
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
select key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
|
select key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
|
||||||
key | count
|
key | count
|
||||||
-----------+-------
|
-----------+-------
|
||||||
line | 883
|
line | 884
|
||||||
query | 207
|
query | 207
|
||||||
pos | 203
|
pos | 203
|
||||||
node | 202
|
node | 202
|
||||||
@ -590,9 +653,9 @@ select key, count(*) from (select (each(h)).key from testhstore) as wow group by
|
|||||||
status | 195
|
status | 195
|
||||||
public | 194
|
public | 194
|
||||||
title | 190
|
title | 190
|
||||||
|
wait | 190
|
||||||
org | 189
|
org | 189
|
||||||
user | 189
|
user | 189
|
||||||
wait | 189
|
|
||||||
coauthors | 188
|
coauthors | 188
|
||||||
disabled | 185
|
disabled | 185
|
||||||
indexed | 184
|
indexed | 184
|
||||||
|
@ -50,4 +50,7 @@ typedef struct
|
|||||||
int comparePairs(const void *a, const void *b);
|
int comparePairs(const void *a, const void *b);
|
||||||
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
|
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
|
||||||
|
|
||||||
|
#define HStoreContainsStrategyNumber 7
|
||||||
|
#define HStoreExistsStrategyNumber 9
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,6 +40,14 @@ RETURNS bool
|
|||||||
AS 'MODULE_PATHNAME','exists'
|
AS 'MODULE_PATHNAME','exists'
|
||||||
LANGUAGE 'C' with (isstrict,iscachable);
|
LANGUAGE 'C' with (isstrict,iscachable);
|
||||||
|
|
||||||
|
CREATE OPERATOR ? (
|
||||||
|
LEFTARG = hstore,
|
||||||
|
RIGHTARG = text,
|
||||||
|
PROCEDURE = exist,
|
||||||
|
RESTRICT = contsel,
|
||||||
|
JOIN = contjoinsel
|
||||||
|
);
|
||||||
|
|
||||||
CREATE FUNCTION isdefined(hstore,text)
|
CREATE FUNCTION isdefined(hstore,text)
|
||||||
RETURNS bool
|
RETURNS bool
|
||||||
AS 'MODULE_PATHNAME','defined'
|
AS 'MODULE_PATHNAME','defined'
|
||||||
@ -116,7 +124,7 @@ CREATE OPERATOR ~ (
|
|||||||
CREATE FUNCTION tconvert(text,text)
|
CREATE FUNCTION tconvert(text,text)
|
||||||
RETURNS hstore
|
RETURNS hstore
|
||||||
AS 'MODULE_PATHNAME'
|
AS 'MODULE_PATHNAME'
|
||||||
LANGUAGE 'C' with (isstrict,iscachable);
|
LANGUAGE 'C' with (iscachable);
|
||||||
|
|
||||||
CREATE OPERATOR => (
|
CREATE OPERATOR => (
|
||||||
LEFTARG = text,
|
LEFTARG = text,
|
||||||
@ -210,7 +218,8 @@ LANGUAGE 'C';
|
|||||||
CREATE OPERATOR CLASS gist_hstore_ops
|
CREATE OPERATOR CLASS gist_hstore_ops
|
||||||
DEFAULT FOR TYPE hstore USING gist
|
DEFAULT FOR TYPE hstore USING gist
|
||||||
AS
|
AS
|
||||||
OPERATOR 7 @> RECHECK,
|
OPERATOR 7 @> RECHECK,
|
||||||
|
OPERATOR 9 ?(hstore,text) RECHECK,
|
||||||
--OPERATOR 8 <@ RECHECK,
|
--OPERATOR 8 <@ RECHECK,
|
||||||
OPERATOR 13 @ RECHECK,
|
OPERATOR 13 @ RECHECK,
|
||||||
--OPERATOR 14 ~ RECHECK,
|
--OPERATOR 14 ~ RECHECK,
|
||||||
@ -223,4 +232,33 @@ AS
|
|||||||
FUNCTION 7 ghstore_same (internal, internal, internal),
|
FUNCTION 7 ghstore_same (internal, internal, internal),
|
||||||
STORAGE ghstore;
|
STORAGE ghstore;
|
||||||
|
|
||||||
|
-- define the GIN support methods
|
||||||
|
|
||||||
|
CREATE FUNCTION gin_extract_hstore(internal, internal)
|
||||||
|
RETURNS internal
|
||||||
|
AS 'MODULE_PATHNAME'
|
||||||
|
LANGUAGE C;
|
||||||
|
|
||||||
|
CREATE FUNCTION gin_extract_hstore_query(internal, internal, int2)
|
||||||
|
RETURNS internal
|
||||||
|
AS 'MODULE_PATHNAME'
|
||||||
|
LANGUAGE C;
|
||||||
|
|
||||||
|
CREATE FUNCTION gin_consistent_hstore(internal, int2, internal)
|
||||||
|
RETURNS internal
|
||||||
|
AS 'MODULE_PATHNAME'
|
||||||
|
LANGUAGE C;
|
||||||
|
|
||||||
|
CREATE OPERATOR CLASS gin_hstore_ops
|
||||||
|
DEFAULT FOR TYPE hstore USING gin
|
||||||
|
AS
|
||||||
|
OPERATOR 7 @> RECHECK,
|
||||||
|
OPERATOR 9 ?(hstore,text),
|
||||||
|
FUNCTION 1 bttextcmp(text,text),
|
||||||
|
FUNCTION 2 gin_extract_hstore(internal, internal),
|
||||||
|
FUNCTION 3 gin_extract_hstore_query(internal, internal, int2),
|
||||||
|
FUNCTION 4 gin_consistent_hstore(internal, int2, internal),
|
||||||
|
STORAGE text;
|
||||||
|
|
||||||
|
|
||||||
END;
|
END;
|
||||||
|
135
contrib/hstore/hstore_gin.c
Normal file
135
contrib/hstore/hstore_gin.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "hstore.h"
|
||||||
|
|
||||||
|
#include "access/gin.h"
|
||||||
|
|
||||||
|
#define KEYFLAG 'K'
|
||||||
|
#define VALFLAG 'V'
|
||||||
|
#define NULLFLAG 'N'
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(gin_extract_hstore);
|
||||||
|
Datum gin_extract_hstore(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
static text*
|
||||||
|
makeitem( char *str, int len )
|
||||||
|
{
|
||||||
|
text *item;
|
||||||
|
|
||||||
|
item = (text*)palloc( VARHDRSZ + len + 1 );
|
||||||
|
SET_VARSIZE(item, VARHDRSZ + len + 1);
|
||||||
|
|
||||||
|
if ( str && len > 0 )
|
||||||
|
memcpy( VARDATA(item)+1, str, len );
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
Datum
|
||||||
|
gin_extract_hstore(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
HStore *hs = PG_GETARG_HS(0);
|
||||||
|
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
||||||
|
Datum *entries = NULL;
|
||||||
|
|
||||||
|
*nentries = 2*hs->size;
|
||||||
|
|
||||||
|
if ( hs->size > 0 )
|
||||||
|
{
|
||||||
|
HEntry *ptr = ARRPTR(hs);
|
||||||
|
char *words = STRPTR(hs);
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
entries = (Datum*)palloc( sizeof(Datum) * 2 * hs->size );
|
||||||
|
|
||||||
|
while (ptr - ARRPTR(hs) < hs->size)
|
||||||
|
{
|
||||||
|
text *item;
|
||||||
|
|
||||||
|
item = makeitem( words + ptr->pos, ptr->keylen );
|
||||||
|
*VARDATA(item) = KEYFLAG;
|
||||||
|
entries[i++] = PointerGetDatum(item);
|
||||||
|
|
||||||
|
if ( ptr->valisnull )
|
||||||
|
{
|
||||||
|
item = makeitem( NULL, 0 );
|
||||||
|
*VARDATA(item) = NULLFLAG;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = makeitem( words + ptr->pos + ptr->keylen, ptr->vallen );
|
||||||
|
*VARDATA(item) = VALFLAG;
|
||||||
|
}
|
||||||
|
entries[i++] = PointerGetDatum(item);
|
||||||
|
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(hs,0);
|
||||||
|
PG_RETURN_POINTER(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
|
||||||
|
Datum gin_extract_hstore_query(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
Datum
|
||||||
|
gin_extract_hstore_query(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
StrategyNumber strategy = PG_GETARG_UINT16(2);
|
||||||
|
|
||||||
|
if ( strategy == HStoreContainsStrategyNumber )
|
||||||
|
{
|
||||||
|
PG_RETURN_DATUM( DirectFunctionCall2(
|
||||||
|
gin_extract_hstore,
|
||||||
|
PG_GETARG_DATUM(0),
|
||||||
|
PG_GETARG_DATUM(1)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else if ( strategy == HStoreExistsStrategyNumber )
|
||||||
|
{
|
||||||
|
text *item, *q = PG_GETARG_TEXT_P(0);
|
||||||
|
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
|
||||||
|
Datum *entries = NULL;
|
||||||
|
|
||||||
|
*nentries = 1;
|
||||||
|
entries = (Datum*)palloc( sizeof(Datum) );
|
||||||
|
|
||||||
|
item = makeitem( VARDATA(q), VARSIZE(q)-VARHDRSZ );
|
||||||
|
*VARDATA(item) = KEYFLAG;
|
||||||
|
entries[0] = PointerGetDatum(item);
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(entries);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elog(ERROR, "Unsupported strategy number: %d", strategy);
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
|
||||||
|
Datum gin_consistent_hstore(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
Datum
|
||||||
|
gin_consistent_hstore(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
StrategyNumber strategy = PG_GETARG_UINT16(1);
|
||||||
|
bool res = true;
|
||||||
|
|
||||||
|
if ( strategy == HStoreContainsStrategyNumber )
|
||||||
|
{
|
||||||
|
bool *check = (bool *) PG_GETARG_POINTER(0);
|
||||||
|
HStore *query = PG_GETARG_HS(2);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0;res && i<2*query->size;i++)
|
||||||
|
if ( check[i] == false )
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
else if ( strategy == HStoreExistsStrategyNumber )
|
||||||
|
res = true;
|
||||||
|
else
|
||||||
|
elog(ERROR, "Unsupported strategy number: %d", strategy);
|
||||||
|
|
||||||
|
PG_RETURN_BOOL(res);
|
||||||
|
}
|
||||||
|
|
@ -492,37 +492,48 @@ Datum
|
|||||||
ghstore_consistent(PG_FUNCTION_ARGS)
|
ghstore_consistent(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GISTTYPE *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
GISTTYPE *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
|
||||||
HStore *query = PG_GETARG_HS(1);
|
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
|
||||||
bool res = true;
|
bool res = true;
|
||||||
HEntry *qe = ARRPTR(query);
|
|
||||||
char *qv = STRPTR(query);
|
|
||||||
BITVECP sign;
|
BITVECP sign;
|
||||||
|
|
||||||
if (ISALLTRUE(entry))
|
if (ISALLTRUE(entry))
|
||||||
{
|
|
||||||
PG_FREE_IF_COPY(query, 1);
|
|
||||||
PG_RETURN_BOOL(true);
|
PG_RETURN_BOOL(true);
|
||||||
}
|
|
||||||
|
|
||||||
sign = GETSIGN(entry);
|
sign = GETSIGN(entry);
|
||||||
while (res && qe - ARRPTR(query) < query->size)
|
|
||||||
|
if ( strategy == HStoreContainsStrategyNumber || strategy == 13 /* hack for old strats */ )
|
||||||
{
|
{
|
||||||
int crc = crc32_sz((char *) (qv + qe->pos), qe->keylen);
|
HStore *query = PG_GETARG_HS(1);
|
||||||
|
HEntry *qe = ARRPTR(query);
|
||||||
|
char *qv = STRPTR(query);
|
||||||
|
|
||||||
if (GETBIT(sign, HASHVAL(crc)))
|
while (res && qe - ARRPTR(query) < query->size)
|
||||||
{
|
{
|
||||||
if (!qe->valisnull)
|
int crc = crc32_sz((char *) (qv + qe->pos), qe->keylen);
|
||||||
{
|
|
||||||
crc = crc32_sz((char *) (qv + qe->pos + qe->keylen), qe->vallen);
|
if (GETBIT(sign, HASHVAL(crc)))
|
||||||
if (!GETBIT(sign, HASHVAL(crc)))
|
{
|
||||||
res = false;
|
if (!qe->valisnull)
|
||||||
}
|
{
|
||||||
}
|
crc = crc32_sz((char *) (qv + qe->pos + qe->keylen), qe->vallen);
|
||||||
else
|
if (!GETBIT(sign, HASHVAL(crc)))
|
||||||
res = false;
|
res = false;
|
||||||
qe++;
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
res = false;
|
||||||
|
qe++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( strategy == HStoreExistsStrategyNumber )
|
||||||
|
{
|
||||||
|
text *query = PG_GETARG_TEXT_P(1);
|
||||||
|
int crc = crc32_sz( VARDATA(query), VARSIZE(query)-VARHDRSZ );
|
||||||
|
|
||||||
|
res = (GETBIT(sign, HASHVAL(crc))) ? true : false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
elog(ERROR, "Unsupported strategy number: %d", strategy);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(query, 1);
|
|
||||||
PG_RETURN_BOOL(res);
|
PG_RETURN_BOOL(res);
|
||||||
}
|
}
|
||||||
|
@ -270,26 +270,48 @@ Datum tconvert(PG_FUNCTION_ARGS);
|
|||||||
Datum
|
Datum
|
||||||
tconvert(PG_FUNCTION_ARGS)
|
tconvert(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *key = PG_GETARG_TEXT_P(0);
|
text *key;
|
||||||
text *val = PG_GETARG_TEXT_P(1);
|
text *val = NULL;
|
||||||
int len;
|
int len;
|
||||||
HStore *out;
|
HStore *out;
|
||||||
|
|
||||||
len = CALCDATASIZE(1, VARSIZE(key) + VARSIZE(val) - 2 * VARHDRSZ);
|
if ( PG_ARGISNULL(0) )
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
|
key = PG_GETARG_TEXT_P(0);
|
||||||
|
|
||||||
|
if ( PG_ARGISNULL(1) )
|
||||||
|
len = CALCDATASIZE(1, VARSIZE(key) );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = PG_GETARG_TEXT_P(1);
|
||||||
|
len = CALCDATASIZE(1, VARSIZE(key) + VARSIZE(val) - 2 * VARHDRSZ);
|
||||||
|
}
|
||||||
out = palloc(len);
|
out = palloc(len);
|
||||||
SET_VARSIZE(out, len);
|
SET_VARSIZE(out, len);
|
||||||
out->size = 1;
|
out->size = 1;
|
||||||
|
|
||||||
ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
|
ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
|
||||||
ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
|
if ( PG_ARGISNULL(1) )
|
||||||
ARRPTR(out)->valisnull = false;
|
{
|
||||||
|
ARRPTR(out)->vallen = 0;
|
||||||
|
ARRPTR(out)->valisnull = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
|
||||||
|
ARRPTR(out)->valisnull = false;
|
||||||
|
}
|
||||||
ARRPTR(out)->pos = 0;
|
ARRPTR(out)->pos = 0;
|
||||||
|
|
||||||
memcpy(STRPTR(out), VARDATA(key), ARRPTR(out)->keylen);
|
memcpy(STRPTR(out), VARDATA(key), ARRPTR(out)->keylen);
|
||||||
memcpy(STRPTR(out) + ARRPTR(out)->keylen, VARDATA(val), ARRPTR(out)->vallen);
|
if (!PG_ARGISNULL(1))
|
||||||
|
{
|
||||||
|
memcpy(STRPTR(out) + ARRPTR(out)->keylen, VARDATA(val), ARRPTR(out)->vallen);
|
||||||
|
PG_FREE_IF_COPY(val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
PG_FREE_IF_COPY(key, 0);
|
PG_FREE_IF_COPY(key, 0);
|
||||||
PG_FREE_IF_COPY(val, 1);
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(out);
|
PG_RETURN_POINTER(out);
|
||||||
}
|
}
|
||||||
@ -515,17 +537,18 @@ hs_contains(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
if (!te->valisnull)
|
if ( te->valisnull || entry->valisnull )
|
||||||
{
|
{
|
||||||
if (entry->valisnull || !(
|
if ( !(te->valisnull && entry->valisnull) )
|
||||||
te->vallen == entry->vallen &&
|
res = false;
|
||||||
|
}
|
||||||
|
else if ( te->vallen != entry->vallen ||
|
||||||
strncmp(
|
strncmp(
|
||||||
vv + entry->pos + entry->keylen,
|
vv + entry->pos + entry->keylen,
|
||||||
tv + te->pos + te->keylen,
|
tv + te->pos + te->keylen,
|
||||||
te->vallen) == 0
|
te->vallen)
|
||||||
))
|
)
|
||||||
res = false;
|
res = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = false;
|
res = false;
|
||||||
|
@ -63,15 +63,18 @@ select 'aa=>b, c=>d , b=>16'::hstore->'b';
|
|||||||
select 'aa=>b, c=>d , b=>16'::hstore->'aa';
|
select 'aa=>b, c=>d , b=>16'::hstore->'aa';
|
||||||
select ('aa=>b, c=>d , b=>16'::hstore->'gg') is null;
|
select ('aa=>b, c=>d , b=>16'::hstore->'gg') is null;
|
||||||
select ('aa=>NULL, c=>d , b=>16'::hstore->'aa') is null;
|
select ('aa=>NULL, c=>d , b=>16'::hstore->'aa') is null;
|
||||||
|
select ('aa=>"NULL", c=>d , b=>16'::hstore->'aa') is null;
|
||||||
|
|
||||||
-- exists/defined
|
-- exists/defined
|
||||||
|
|
||||||
select exist('a=>NULL, b=>qq', 'a');
|
select exist('a=>NULL, b=>qq', 'a');
|
||||||
select exist('a=>NULL, b=>qq', 'b');
|
select exist('a=>NULL, b=>qq', 'b');
|
||||||
select exist('a=>NULL, b=>qq', 'c');
|
select exist('a=>NULL, b=>qq', 'c');
|
||||||
|
select exist('a=>"NULL", b=>qq', 'a');
|
||||||
select defined('a=>NULL, b=>qq', 'a');
|
select defined('a=>NULL, b=>qq', 'a');
|
||||||
select defined('a=>NULL, b=>qq', 'b');
|
select defined('a=>NULL, b=>qq', 'b');
|
||||||
select defined('a=>NULL, b=>qq', 'c');
|
select defined('a=>NULL, b=>qq', 'c');
|
||||||
|
select defined('a=>"NULL", b=>qq', 'a');
|
||||||
|
|
||||||
-- delete
|
-- delete
|
||||||
|
|
||||||
@ -91,6 +94,8 @@ select ''::hstore || 'cq=>l, b=>g, fg=>f';
|
|||||||
-- =>
|
-- =>
|
||||||
select 'a=>g, b=>c'::hstore || ( 'asd'=>'gf' );
|
select 'a=>g, b=>c'::hstore || ( 'asd'=>'gf' );
|
||||||
select 'a=>g, b=>c'::hstore || ( 'b'=>'gf' );
|
select 'a=>g, b=>c'::hstore || ( 'b'=>'gf' );
|
||||||
|
select 'a=>g, b=>c'::hstore || ( 'b'=>'NULL' );
|
||||||
|
select 'a=>g, b=>c'::hstore || ( 'b'=>NULL );
|
||||||
|
|
||||||
-- keys/values
|
-- keys/values
|
||||||
select akeys('aa=>1 , b=>2, cq=>3'::hstore || 'cq=>l, b=>g, fg=>f');
|
select akeys('aa=>1 , b=>2, cq=>3'::hstore || 'cq=>l, b=>g, fg=>f');
|
||||||
@ -112,13 +117,12 @@ select * from svals('');
|
|||||||
select * from each('aaa=>bq, b=>NULL, ""=>1 ');
|
select * from each('aaa=>bq, b=>NULL, ""=>1 ');
|
||||||
|
|
||||||
-- @>
|
-- @>
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, c=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>NULL';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, g=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, g=>NULL';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'g=>NULL';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'g=>NULL';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>c';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>c';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>NULL';
|
|
||||||
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>q';
|
select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b, c=>q';
|
||||||
|
|
||||||
CREATE TABLE testhstore (h hstore);
|
CREATE TABLE testhstore (h hstore);
|
||||||
@ -127,6 +131,7 @@ CREATE TABLE testhstore (h hstore);
|
|||||||
select count(*) from testhstore where h @> 'wait=>NULL';
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
select count(*) from testhstore where h @> 'wait=>CC';
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
|
||||||
create index hidx on testhstore using gist(h);
|
create index hidx on testhstore using gist(h);
|
||||||
set enable_seqscan=off;
|
set enable_seqscan=off;
|
||||||
@ -134,6 +139,16 @@ set enable_seqscan=off;
|
|||||||
select count(*) from testhstore where h @> 'wait=>NULL';
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
select count(*) from testhstore where h @> 'wait=>CC';
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
|
||||||
|
drop index hidx;
|
||||||
|
create index hidx on testhstore using gin (h);
|
||||||
|
set enable_seqscan=off;
|
||||||
|
|
||||||
|
select count(*) from testhstore where h @> 'wait=>NULL';
|
||||||
|
select count(*) from testhstore where h @> 'wait=>CC';
|
||||||
|
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
|
||||||
|
select count(*) from testhstore where h ? 'public';
|
||||||
|
|
||||||
select count(*) from (select (each(h)).key from testhstore) as wow ;
|
select count(*) from (select (each(h)).key from testhstore) as wow ;
|
||||||
select key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
|
select key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
DROP OPERATOR CLASS gist_hstore_ops USING gist CASCADE;
|
DROP OPERATOR CLASS gist_hstore_ops USING gist CASCADE;
|
||||||
|
DROP OPERATOR CLASS gin_hstore_ops USING gin CASCADE;
|
||||||
|
|
||||||
|
DROP OPERATOR ? ( hstore, text );
|
||||||
DROP OPERATOR ->( hstore, text );
|
DROP OPERATOR ->( hstore, text );
|
||||||
DROP OPERATOR ||( hstore, hstore );
|
DROP OPERATOR ||( hstore, hstore );
|
||||||
DROP OPERATOR @>( hstore, hstore );
|
DROP OPERATOR @>( hstore, hstore );
|
||||||
@ -33,6 +35,9 @@ DROP FUNCTION ghstore_picksplit(internal, internal);
|
|||||||
DROP FUNCTION ghstore_union(internal, internal);
|
DROP FUNCTION ghstore_union(internal, internal);
|
||||||
DROP FUNCTION ghstore_same(internal, internal, internal);
|
DROP FUNCTION ghstore_same(internal, internal, internal);
|
||||||
DROP FUNCTION ghstore_consistent(internal,internal,int4);
|
DROP FUNCTION ghstore_consistent(internal,internal,int4);
|
||||||
|
DROP FUNCTION gin_consistent_hstore(internal, smallint, internal);
|
||||||
|
DROP FUNCTION gin_extract_hstore(internal, internal);
|
||||||
|
DROP FUNCTION gin_extract_hstore_query(internal, internal, smallint);
|
||||||
|
|
||||||
DROP TYPE hstore CASCADE;
|
DROP TYPE hstore CASCADE;
|
||||||
DROP TYPE hs_each CASCADE;
|
DROP TYPE hs_each CASCADE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user