aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/hstore/Makefile4
-rw-r--r--contrib/hstore/README.hstore16
-rw-r--r--contrib/hstore/data/hstore.data1
-rw-r--r--contrib/hstore/expected/hstore.out91
-rw-r--r--contrib/hstore/hstore.h3
-rw-r--r--contrib/hstore/hstore.sql.in42
-rw-r--r--contrib/hstore/hstore_gin.c135
-rw-r--r--contrib/hstore/hstore_gist.c45
-rw-r--r--contrib/hstore/hstore_op.c49
-rw-r--r--contrib/hstore/sql/hstore.sql23
-rw-r--r--contrib/hstore/uninstall_hstore.sql5
11 files changed, 355 insertions, 59 deletions
diff --git a/contrib/hstore/Makefile b/contrib/hstore/Makefile
index d15d2ae775a..5257bbfcc00 100644
--- a/contrib/hstore/Makefile
+++ b/contrib/hstore/Makefile
@@ -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
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
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 = uninstall_hstore.sql
diff --git a/contrib/hstore/README.hstore b/contrib/hstore/README.hstore
index 5fdceb1b986..b8c97113893 100644
--- a/contrib/hstore/README.hstore
+++ b/contrib/hstore/README.hstore
@@ -117,13 +117,14 @@ regression=# select * from each('a=>1,b=>2');
a | 1
b | 2
- * exist (hstore,text) - returns 'true if key is exists in hstore and
- false otherwise.
+ * exist (hstore,text)
+ * hstore ? text
+ - returns 'true if key is exists in hstore and false otherwise.
-regression=# select exist('a=>1','a');
- exist
-----------
- t
+regression=# select exist('a=>1','a'), 'a=>1' ? 'a';
+ exist | ?column?
+-------+----------
+ t | t
* defined (hstore,text) - returns true if key is exists in hstore and
its value is not NULL.
@@ -135,9 +136,10 @@ regression=# select defined('a=>NULL','a');
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 gin(h);
Note
diff --git a/contrib/hstore/data/hstore.data b/contrib/hstore/data/hstore.data
index 7651a10f084..b7391daffb7 100644
--- a/contrib/hstore/data/hstore.data
+++ b/contrib/hstore/data/hstore.data
@@ -998,3 +998,4 @@ auth=>BC, title=>CAC, subtitle=>BA, line=>997, date=>BAA
wait=>AB, user=>ABC, line=>998, pos=>41, node=>CAC
state=>4, title=>AC, bad=>t, status=>59, line=>999, disabled=>t
user=>BC, line=>1000
+wait=>NULL, line=>1000
diff --git a/contrib/hstore/expected/hstore.out b/contrib/hstore/expected/hstore.out
index 94194a6d00b..eee23d3a05a 100644
--- a/contrib/hstore/expected/hstore.out
+++ b/contrib/hstore/expected/hstore.out
@@ -272,6 +272,12 @@ select ('aa=>NULL, c=>d , b=>16'::hstore->'aa') is null;
t
(1 row)
+select ('aa=>"NULL", c=>d , b=>16'::hstore->'aa') is null;
+ ?column?
+----------
+ f
+(1 row)
+
-- exists/defined
select exist('a=>NULL, b=>qq', 'a');
exist
@@ -291,6 +297,12 @@ select exist('a=>NULL, b=>qq', 'c');
f
(1 row)
+select exist('a=>"NULL", b=>qq', 'a');
+ exist
+-------
+ t
+(1 row)
+
select defined('a=>NULL, b=>qq', 'a');
defined
---------
@@ -309,6 +321,12 @@ select defined('a=>NULL, b=>qq', 'c');
f
(1 row)
+select defined('a=>"NULL", b=>qq', 'a');
+ defined
+---------
+ t
+(1 row)
+
-- delete
select delete('a=>1 , b=>2, c=>3'::hstore, 'a');
delete
@@ -384,6 +402,18 @@ select 'a=>g, b=>c'::hstore || ( 'b'=>'gf' );
"a"=>"g", "b"=>"gf"
(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
select akeys('aa=>1 , b=>2, cq=>3'::hstore || 'cq=>l, b=>g, fg=>f');
akeys
@@ -485,19 +515,19 @@ select * from each('aaa=>bq, b=>NULL, ""=>1 ');
(3 rows)
-- @>
-select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL';
+select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
?column?
----------
t
(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?
----------
t
(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?
----------
f
@@ -521,12 +551,6 @@ select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>b';
t
(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';
?column?
----------
@@ -538,7 +562,7 @@ CREATE TABLE testhstore (h hstore);
select count(*) from testhstore where h @> 'wait=>NULL';
count
-------
- 189
+ 1
(1 row)
select count(*) from testhstore where h @> 'wait=>CC';
@@ -553,12 +577,18 @@ select count(*) from testhstore where h @> 'wait=>CC, public=>t';
2
(1 row)
+select count(*) from testhstore where h ? 'public';
+ count
+-------
+ 194
+(1 row)
+
create index hidx on testhstore using gist(h);
set enable_seqscan=off;
select count(*) from testhstore where h @> 'wait=>NULL';
count
-------
- 189
+ 1
(1 row)
select count(*) from testhstore where h @> 'wait=>CC';
@@ -573,16 +603,49 @@ select count(*) from testhstore where h @> 'wait=>CC, public=>t';
2
(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 ;
count
-------
- 4779
+ 4781
(1 row)
select key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
key | count
-----------+-------
- line | 883
+ line | 884
query | 207
pos | 203
node | 202
@@ -590,9 +653,9 @@ select key, count(*) from (select (each(h)).key from testhstore) as wow group by
status | 195
public | 194
title | 190
+ wait | 190
org | 189
user | 189
- wait | 189
coauthors | 188
disabled | 185
indexed | 184
diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index a601906764b..5ef18abd8e8 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -50,4 +50,7 @@ typedef struct
int comparePairs(const void *a, const void *b);
int uniquePairs(Pairs * a, int4 l, int4 *buflen);
+#define HStoreContainsStrategyNumber 7
+#define HStoreExistsStrategyNumber 9
+
#endif
diff --git a/contrib/hstore/hstore.sql.in b/contrib/hstore/hstore.sql.in
index 95cecf15d29..3e0821a9525 100644
--- a/contrib/hstore/hstore.sql.in
+++ b/contrib/hstore/hstore.sql.in
@@ -40,6 +40,14 @@ RETURNS bool
AS 'MODULE_PATHNAME','exists'
LANGUAGE 'C' with (isstrict,iscachable);
+CREATE OPERATOR ? (
+ LEFTARG = hstore,
+ RIGHTARG = text,
+ PROCEDURE = exist,
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
CREATE FUNCTION isdefined(hstore,text)
RETURNS bool
AS 'MODULE_PATHNAME','defined'
@@ -116,7 +124,7 @@ CREATE OPERATOR ~ (
CREATE FUNCTION tconvert(text,text)
RETURNS hstore
AS 'MODULE_PATHNAME'
-LANGUAGE 'C' with (isstrict,iscachable);
+LANGUAGE 'C' with (iscachable);
CREATE OPERATOR => (
LEFTARG = text,
@@ -210,7 +218,8 @@ LANGUAGE 'C';
CREATE OPERATOR CLASS gist_hstore_ops
DEFAULT FOR TYPE hstore USING gist
AS
- OPERATOR 7 @> RECHECK,
+ OPERATOR 7 @> RECHECK,
+ OPERATOR 9 ?(hstore,text) RECHECK,
--OPERATOR 8 <@ RECHECK,
OPERATOR 13 @ RECHECK,
--OPERATOR 14 ~ RECHECK,
@@ -223,4 +232,33 @@ AS
FUNCTION 7 ghstore_same (internal, internal, internal),
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;
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
new file mode 100644
index 00000000000..f6fab2b89d6
--- /dev/null
+++ b/contrib/hstore/hstore_gin.c
@@ -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);
+}
+
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index c3923dacf25..fbee64be7da 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -492,37 +492,48 @@ Datum
ghstore_consistent(PG_FUNCTION_ARGS)
{
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;
- HEntry *qe = ARRPTR(query);
- char *qv = STRPTR(query);
BITVECP sign;
if (ISALLTRUE(entry))
- {
- PG_FREE_IF_COPY(query, 1);
PG_RETURN_BOOL(true);
- }
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);
+
+ if (GETBIT(sign, HASHVAL(crc)))
{
- crc = crc32_sz((char *) (qv + qe->pos + qe->keylen), qe->vallen);
- if (!GETBIT(sign, HASHVAL(crc)))
- res = false;
+ if (!qe->valisnull)
+ {
+ crc = crc32_sz((char *) (qv + qe->pos + qe->keylen), qe->vallen);
+ if (!GETBIT(sign, HASHVAL(crc)))
+ res = false;
+ }
}
+ else
+ 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);
}
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index ef3eb86ca3e..326948afc14 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -270,26 +270,48 @@ Datum tconvert(PG_FUNCTION_ARGS);
Datum
tconvert(PG_FUNCTION_ARGS)
{
- text *key = PG_GETARG_TEXT_P(0);
- text *val = PG_GETARG_TEXT_P(1);
+ text *key;
+ text *val = NULL;
int len;
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);
SET_VARSIZE(out, len);
out->size = 1;
ARRPTR(out)->keylen = VARSIZE(key) - VARHDRSZ;
- ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
- ARRPTR(out)->valisnull = false;
+ if ( PG_ARGISNULL(1) )
+ {
+ ARRPTR(out)->vallen = 0;
+ ARRPTR(out)->valisnull = true;
+ }
+ else
+ {
+ ARRPTR(out)->vallen = VARSIZE(val) - VARHDRSZ;
+ ARRPTR(out)->valisnull = false;
+ }
ARRPTR(out)->pos = 0;
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(val, 1);
PG_RETURN_POINTER(out);
}
@@ -515,17 +537,18 @@ hs_contains(PG_FUNCTION_ARGS)
if (entry)
{
- if (!te->valisnull)
+ if ( te->valisnull || entry->valisnull )
{
- if (entry->valisnull || !(
- te->vallen == entry->vallen &&
+ if ( !(te->valisnull && entry->valisnull) )
+ res = false;
+ }
+ else if ( te->vallen != entry->vallen ||
strncmp(
vv + entry->pos + entry->keylen,
tv + te->pos + te->keylen,
- te->vallen) == 0
- ))
+ te->vallen)
+ )
res = false;
- }
}
else
res = false;
diff --git a/contrib/hstore/sql/hstore.sql b/contrib/hstore/sql/hstore.sql
index f268da557c8..9da6cd13dff 100644
--- a/contrib/hstore/sql/hstore.sql
+++ b/contrib/hstore/sql/hstore.sql
@@ -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->'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;
-- exists/defined
select exist('a=>NULL, b=>qq', 'a');
select exist('a=>NULL, b=>qq', 'b');
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', 'b');
select defined('a=>NULL, b=>qq', 'c');
+select defined('a=>"NULL", b=>qq', 'a');
-- 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 || ( 'b'=>'gf' );
+select 'a=>g, b=>c'::hstore || ( 'b'=>'NULL' );
+select 'a=>g, b=>c'::hstore || ( 'b'=>NULL );
-- keys/values
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 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL';
-select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, c=>NULL';
-select 'a=>b, b=>1, c=>NULL'::hstore @> 'a=>NULL, g=>NULL';
+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, 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=>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';
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=>CC';
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);
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=>CC';
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 key, count(*) from (select (each(h)).key from testhstore) as wow group by key order by count desc, key;
diff --git a/contrib/hstore/uninstall_hstore.sql b/contrib/hstore/uninstall_hstore.sql
index bfa2e738dce..a24bc72f9f8 100644
--- a/contrib/hstore/uninstall_hstore.sql
+++ b/contrib/hstore/uninstall_hstore.sql
@@ -1,7 +1,9 @@
BEGIN;
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, hstore );
DROP OPERATOR @>( hstore, hstore );
@@ -33,6 +35,9 @@ DROP FUNCTION ghstore_picksplit(internal, internal);
DROP FUNCTION ghstore_union(internal, internal);
DROP FUNCTION ghstore_same(internal, internal, internal);
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 hs_each CASCADE;