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:
Teodor Sigaev 2007-03-14 14:21:53 +00:00
parent 15f91f2789
commit 754148d81f
11 changed files with 359 additions and 63 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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);
}

View File

@ -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);
} }

View File

@ -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;

View File

@ -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;

View File

@ -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;