Commit 172eacba authored by Tom Lane's avatar Tom Lane

Assorted improvements in contrib/hstore.

Remove the 64K limit on the lengths of keys and values within an hstore.
(This changes the on-disk format, but the old format can still be read.)
Add support for btree/hash opclasses for hstore --- this is not so much
for actual indexing purposes as to allow use of GROUP BY, DISTINCT, etc.
Add various other new functions and operators.

Andrew Gierth
parent 1d43e531
# $PostgreSQL: pgsql/contrib/hstore/Makefile,v 1.6 2007/11/10 23:59:51 momjian Exp $
# $PostgreSQL: pgsql/contrib/hstore/Makefile,v 1.7 2009/09/30 19:50:22 tgl 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 hstore_gin.o crc32.o
OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o hstore_compat.o \
crc32.o
DATA_built = hstore.sql
DATA = uninstall_hstore.sql
......
This diff is collapsed.
/*
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.8 2009/06/11 14:48:51 momjian Exp $
* $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.9 2009/09/30 19:50:22 tgl Exp $
*/
#ifndef __HSTORE_H__
#define __HSTORE_H__
#include "fmgr.h"
#include "utils/array.h"
/*
* HEntry: there is one of these for each key _and_ value in an hstore
*
* the position offset points to the _end_ so that we can get the length
* by subtraction from the previous entry. the ISFIRST flag lets us tell
* whether there is a previous entry.
*/
typedef struct
{
uint16 keylen;
uint16 vallen;
uint32
valisnull:1,
pos:31;
uint32 entry;
} HEntry;
/* these are determined by the sizes of the keylen and vallen fields */
/* in struct HEntry and struct Pairs */
#define HSTORE_MAX_KEY_LEN 65535
#define HSTORE_MAX_VALUE_LEN 65535
#define HENTRY_ISFIRST 0x80000000
#define HENTRY_ISNULL 0x40000000
#define HENTRY_POSMASK 0x3FFFFFFF
/* note possible multiple evaluations, also access to prior array element */
#define HSE_ISFIRST(he_) (((he_).entry & HENTRY_ISFIRST) != 0)
#define HSE_ISNULL(he_) (((he_).entry & HENTRY_ISNULL) != 0)
#define HSE_ENDPOS(he_) ((he_).entry & HENTRY_POSMASK)
#define HSE_OFF(he_) (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1]))
#define HSE_LEN(he_) (HSE_ISFIRST(he_) \
? HSE_ENDPOS(he_) \
: HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))
/*
* determined by the size of "endpos" (ie HENTRY_POSMASK), though this is a
* bit academic since currently varlenas (and hence both the input and the
* whole hstore) have the same limit
*/
#define HSTORE_MAX_KEY_LEN 0x3FFFFFFF
#define HSTORE_MAX_VALUE_LEN 0x3FFFFFFF
typedef struct
{
int32 vl_len_; /* varlena header (do not touch directly!) */
int4 size;
char data[1];
uint32 size_; /* flags and number of items in hstore */
/* array of HEntry follows */
} HStore;
#define HSHRDSIZE (VARHDRSZ + sizeof(int4))
#define CALCDATASIZE(x, lenstr) ( (x) * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
#define ARRPTR(x) ( (HEntry*) ( (char*)(x) + HSHRDSIZE ) )
#define STRPTR(x) ( (char*)(x) + HSHRDSIZE + ( sizeof(HEntry) * ((HStore*)x)->size ) )
/*
* it's not possible to get more than 2^28 items into an hstore,
* so we reserve the top few bits of the size field. See hstore_compat.c
* for one reason why. Some bits are left for future use here.
*/
#define HS_FLAG_NEWVERSION 0x80000000
#define HS_COUNT(hsp_) ((hsp_)->size_ & 0x0FFFFFFF)
#define HS_SETCOUNT(hsp_,c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
#define HSHRDSIZE (sizeof(HStore))
#define CALCDATASIZE(x, lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
/* note multiple evaluations of x */
#define ARRPTR(x) ( (HEntry*) ( (HStore*)(x) + 1 ) )
#define STRPTR(x) ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )
/* note multiple/non evaluations */
#define HS_KEY(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)]))
#define HS_VAL(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)+1]))
#define HS_KEYLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)]))
#define HS_VALLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)+1]))
#define HS_VALISNULL(arr_,i_) (HSE_ISNULL((arr_)[2*(i_)+1]))
/*
* currently, these following macros are the _only_ places that rely
* on internal knowledge of HEntry. Everything else should be using
* the above macros. Exception: the in-place upgrade in hstore_compat.c
* messes with entries directly.
*/
/*
* copy one key/value pair (which must be contiguous starting at
* sptr_) into an under-construction hstore; dent_ is an HEntry*,
* dbuf_ is the destination's string buffer, dptr_ is the current
* position in the destination. lots of modification and multiple
* evaluation here.
*/
#define HS_COPYITEM(dent_,dbuf_,dptr_,sptr_,klen_,vlen_,vnull_) \
do { \
memcpy((dptr_), (sptr_), (klen_)+(vlen_)); \
(dptr_) += (klen_)+(vlen_); \
(dent_)++->entry = ((dptr_) - (dbuf_) - (vlen_)) & HENTRY_POSMASK; \
(dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
| ((vnull_) ? HENTRY_ISNULL : 0)); \
} while(0)
/*
* add one key/item pair, from a Pairs structure, into an
* under-construction hstore
*/
#define HS_ADDITEM(dent_,dbuf_,dptr_,pair_) \
do { \
memcpy((dptr_), (pair_).key, (pair_).keylen); \
(dptr_) += (pair_).keylen; \
(dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
if ((pair_).isnull) \
(dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
| HENTRY_ISNULL); \
else \
{ \
memcpy((dptr_), (pair_).val, (pair_).vallen); \
(dptr_) += (pair_).vallen; \
(dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
} \
} while (0)
/* finalize a newly-constructed hstore */
#define HS_FINALIZE(hsp_,count_,buf_,ptr_) \
do { \
int buflen = (ptr_) - (buf_); \
if ((count_)) \
ARRPTR(hsp_)[0].entry |= HENTRY_ISFIRST; \
if ((count_) != HS_COUNT((hsp_))) \
{ \
HS_SETCOUNT((hsp_),(count_)); \
memmove(STRPTR(hsp_), (buf_), buflen); \
} \
SET_VARSIZE((hsp_), CALCDATASIZE((count_), buflen)); \
} while (0)
/* ensure the varlena size of an existing hstore is correct */
#define HS_FIXSIZE(hsp_,count_) \
do { \
int bl = (count_) ? HSE_ENDPOS(ARRPTR(hsp_)[2*(count_)-1]) : 0; \
SET_VARSIZE((hsp_), CALCDATASIZE((count_),bl)); \
} while (0)
/* DatumGetHStoreP includes support for reading old-format hstore values */
extern HStore *hstoreUpgrade(Datum orig);
#define DatumGetHStoreP(d) hstoreUpgrade(d)
#define PG_GETARG_HS(x) ((HStore*)PG_DETOAST_DATUM(PG_GETARG_DATUM(x)))
#define PG_GETARG_HS(x) DatumGetHStoreP(PG_GETARG_DATUM(x))
/*
* Pairs is a "decompressed" representation of one key/value pair.
* The two strings are not necessarily null-terminated.
*/
typedef struct
{
char *key;
char *val;
uint16 keylen;
uint16 vallen;
bool isnull;
bool needfree;
size_t keylen;
size_t vallen;
bool isnull; /* value is null? */
bool needfree; /* need to pfree the value? */
} Pairs;
int comparePairs(const void *a, const void *b);
int uniquePairs(Pairs *a, int4 l, int4 *buflen);
extern int hstoreUniquePairs(Pairs *a, int4 l, int4 *buflen);
extern HStore *hstorePairs(Pairs *pairs, int4 pcount, int4 buflen);
extern size_t hstoreCheckKeyLen(size_t len);
extern size_t hstoreCheckValLen(size_t len);
size_t hstoreCheckKeyLen(size_t len);
size_t hstoreCheckValLen(size_t len);
extern int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
#define HStoreContainsStrategyNumber 7
#define HStoreExistsStrategyNumber 9
#define HStoreExistsAnyStrategyNumber 10
#define HStoreExistsAllStrategyNumber 11
#define HStoreOldContainsStrategyNumber 13 /* backwards compatibility */
/*
* defining HSTORE_POLLUTE_NAMESPACE=0 will prevent use of old function names;
* for now, we default to on for the benefit of people restoring old dumps
*/
#ifndef HSTORE_POLLUTE_NAMESPACE
#define HSTORE_POLLUTE_NAMESPACE 1
#endif
#if HSTORE_POLLUTE_NAMESPACE
#define HSTORE_POLLUTE(newname_,oldname_) \
PG_FUNCTION_INFO_V1(oldname_); \
Datum oldname_(PG_FUNCTION_ARGS); \
Datum newname_(PG_FUNCTION_ARGS); \
Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
extern int no_such_variable
#else
#define HSTORE_POLLUTE(newname_,oldname_) \
extern int no_such_variable
#endif
#endif /* __HSTORE_H__ */
This diff is collapsed.
This diff is collapsed.
/*
* $PostgreSQL: pgsql/contrib/hstore/hstore_gin.c,v 1.6 2009/06/11 14:48:51 momjian Exp $
* $PostgreSQL: pgsql/contrib/hstore/hstore_gin.c,v 1.7 2009/09/30 19:50:22 tgl Exp $
*/
#include "postgres.h"
#include "access/gin.h"
#include "catalog/pg_type.h"
#include "hstore.h"
......@@ -35,43 +36,36 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
HStore *hs = PG_GETARG_HS(0);
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
Datum *entries = NULL;
HEntry *hsent = ARRPTR(hs);
char *ptr = STRPTR(hs);
int count = HS_COUNT(hs);
int i;
*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);
*nentries = 2 * count;
if (count)
entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
while (ptr - ARRPTR(hs) < hs->size)
for (i = 0; i < count; ++i)
{
text *item;
item = makeitem(words + ptr->pos, ptr->keylen);
item = makeitem(HS_KEY(hsent,ptr,i), HS_KEYLEN(hsent,i));
*VARDATA(item) = KEYFLAG;
entries[i++] = PointerGetDatum(item);
entries[2*i] = PointerGetDatum(item);
if (ptr->valisnull)
if (HS_VALISNULL(hsent,i))
{
item = makeitem(NULL, 0);
*VARDATA(item) = NULLFLAG;
}
else
{
item = makeitem(words + ptr->pos + ptr->keylen, ptr->vallen);
item = makeitem(HS_VAL(hsent,ptr,i), HS_VALLEN(hsent,i));
*VARDATA(item) = VALFLAG;
}
entries[i++] = PointerGetDatum(item);
ptr++;
}
entries[2*i+1] = PointerGetDatum(item);
}
PG_FREE_IF_COPY(hs, 0);
PG_RETURN_POINTER(entries);
}
......@@ -85,8 +79,7 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
if (strategy == HStoreContainsStrategyNumber)
{
PG_RETURN_DATUM(DirectFunctionCall2(
gin_extract_hstore,
PG_RETURN_DATUM(DirectFunctionCall2(gin_extract_hstore,
PG_GETARG_DATUM(0),
PG_GETARG_DATUM(1)
));
......@@ -94,19 +87,50 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
else if (strategy == HStoreExistsStrategyNumber)
{
text *item,
*q = PG_GETARG_TEXT_P(0);
*query = PG_GETARG_TEXT_PP(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);
item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
*VARDATA(item) = KEYFLAG;
entries[0] = PointerGetDatum(item);
PG_RETURN_POINTER(entries);
}
else if (strategy == HStoreExistsAnyStrategyNumber ||
strategy == HStoreExistsAllStrategyNumber)
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
Datum *key_datums;
bool *key_nulls;
int key_count;
int i,j;
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
Datum *entries = NULL;
text *item;
deconstruct_array(query,
TEXTOID, -1, false, 'i',
&key_datums, &key_nulls, &key_count);
entries = (Datum *) palloc(sizeof(Datum) * key_count);
for (i = 0, j = 0; i < key_count; ++i)
{
if (key_nulls[i])
continue;
item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
*VARDATA(item) = KEYFLAG;
entries[j++] = PointerGetDatum(item);
}
*nentries = j ? j : -1;
PG_RETURN_POINTER(entries);
}
else
elog(ERROR, "Unsupported strategy number: %d", strategy);
......@@ -121,32 +145,45 @@ gin_consistent_hstore(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
HStore *query = PG_GETARG_HS(2);
/* int32 nkeys = PG_GETARG_INT32(3); */
/* HStore *query = PG_GETARG_HS(2); */
int32 nkeys = PG_GETARG_INT32(3);
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res = true;
*recheck = false;
if (strategy == HStoreContainsStrategyNumber)
{
int i;
/*
* Index lost information about correspondence of keys and values, so
* we need recheck
* we need recheck (pre-8.4 this is handled at SQL level)
*/
*recheck = true;
for (i = 0; res && i < 2 * query->size; i++)
for (i = 0; res && i < nkeys; i++)
if (check[i] == false)
res = false;
}
else if (strategy == HStoreExistsStrategyNumber)
{
/* Existence of key is guaranteed */
*recheck = false;
res = true;
}
else if (strategy == HStoreExistsAnyStrategyNumber)
{
/* Existence of key is guaranteed */
res = true;
}
else if (strategy == HStoreExistsAllStrategyNumber)
{
int i;
for (i = 0; res && i < nkeys; ++i)
if (!check[i])
res = false;
}
else
elog(ERROR, "Unsupported strategy number: %d", strategy);
......
/*
* $PostgreSQL: pgsql/contrib/hstore/hstore_gist.c,v 1.10 2009/06/11 14:48:51 momjian Exp $
* $PostgreSQL: pgsql/contrib/hstore/hstore_gist.c,v 1.11 2009/09/30 19:50:22 tgl Exp $
*/
#include "postgres.h"
#include "access/gist.h"
#include "access/itup.h"
#include "access/skey.h"
#include "crc32.h"
#include "catalog/pg_type.h"
#include "crc32.h"
#include "hstore.h"
/* bigint defines */
......@@ -114,30 +115,27 @@ ghstore_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
HStore *toastedval = (HStore *) DatumGetPointer(entry->key);
HStore *val = (HStore *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
HEntry *ptr = ARRPTR(val);
char *words = STRPTR(val);
HStore *val = DatumGetHStoreP(entry->key);
HEntry *hsent = ARRPTR(val);
char *ptr = STRPTR(val);
int count = HS_COUNT(val);
int i;
SET_VARSIZE(res, CALCGTSIZE(0));
while (ptr - ARRPTR(val) < val->size)
for (i = 0; i < count; ++i)
{
int h;
h = crc32_sz((char *) (words + ptr->pos), ptr->keylen);
h = crc32_sz((char *) HS_KEY(hsent,ptr,i), HS_KEYLEN(hsent,i));
HASH(GETSIGN(res), h);
if (!ptr->valisnull)
if (!HS_VALISNULL(hsent,i))
{
h = crc32_sz((char *) (words + ptr->pos + ptr->keylen), ptr->vallen);
h = crc32_sz((char *) HS_VAL(hsent,ptr,i), HS_VALLEN(hsent,i));
HASH(GETSIGN(res), h);
}
ptr++;
}
if (val != toastedval)
pfree(val);
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(res),
entry->rel, entry->page,
......@@ -177,7 +175,7 @@ ghstore_decompress(PG_FUNCTION_ARGS)
GISTENTRY *retval;
HStore *key;
key = (HStore *) PG_DETOAST_DATUM(entry->key);
key = DatumGetHStoreP(entry->key);
if (key != (HStore *) DatumGetPointer(entry->key))
{
......@@ -500,7 +498,6 @@ ghstore_picksplit(PG_FUNCTION_ARGS)
}
*right = *left = FirstOffsetNumber;
pfree(costvector);
v->spl_ldatum = PointerGetDatum(datum_l);
v->spl_rdatum = PointerGetDatum(datum_r);
......@@ -514,7 +511,6 @@ ghstore_consistent(PG_FUNCTION_ARGS)
{
GISTTYPE *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
bool res = true;
......@@ -528,37 +524,85 @@ ghstore_consistent(PG_FUNCTION_ARGS)
sign = GETSIGN(entry);
if (strategy == HStoreContainsStrategyNumber || strategy == 13 /* hack for old strats */ )
if (strategy == HStoreContainsStrategyNumber ||
strategy == HStoreOldContainsStrategyNumber)
{
HStore *query = PG_GETARG_HS(1);
HEntry *qe = ARRPTR(query);
char *qv = STRPTR(query);
int count = HS_COUNT(query);
int i;
while (res && qe - ARRPTR(query) < query->size)
for (i = 0; res && i < count; ++i)
{
int crc = crc32_sz((char *) (qv + qe->pos), qe->keylen);
int crc = crc32_sz((char *) HS_KEY(qe,qv,i), HS_KEYLEN(qe,i));
if (GETBIT(sign, HASHVAL(crc)))
{
if (!qe->valisnull)
if (!HS_VALISNULL(qe,i))
{
crc = crc32_sz((char *) (qv + qe->pos + qe->keylen), qe->vallen);
crc = crc32_sz((char *) HS_VAL(qe,qv,i), HS_VALLEN(qe,i));
if (!GETBIT(sign, HASHVAL(crc)))
res = false;
}
}
else
res = false;
qe++;
}
}
else if (strategy == HStoreExistsStrategyNumber)
{
text *query = PG_GETARG_TEXT_P(1);
int crc = crc32_sz(VARDATA(query), VARSIZE(query) - VARHDRSZ);
text *query = PG_GETARG_TEXT_PP(1);
int crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
res = (GETBIT(sign, HASHVAL(crc))) ? true : false;
}
else if (strategy == HStoreExistsAllStrategyNumber)
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
Datum *key_datums;
bool *key_nulls;
int key_count;
int i;
deconstruct_array(query,
TEXTOID, -1, false, 'i',
&key_datums, &key_nulls, &key_count);
for (i = 0; res && i < key_count; ++i)
{
int crc;
if (key_nulls[i])
continue;
crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
if (!(GETBIT(sign, HASHVAL(crc))))
res = FALSE;
}
}
else if (strategy == HStoreExistsAnyStrategyNumber)
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
Datum *key_datums;
bool *key_nulls;
int key_count;
int i;
deconstruct_array(query,
TEXTOID, -1, false, 'i',
&key_datums, &key_nulls, &key_count);
res = FALSE;
for (i = 0; !res && i < key_count; ++i)
{
int crc;
if (key_nulls[i])
continue;
crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
if (GETBIT(sign, HASHVAL(crc)))
res = TRUE;
}
}
else
elog(ERROR, "Unsupported strategy number: %d", strategy);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* $PostgreSQL: pgsql/contrib/hstore/uninstall_hstore.sql,v 1.8 2009/03/25 22:19:01 tgl Exp $ */
/* $PostgreSQL: pgsql/contrib/hstore/uninstall_hstore.sql,v 1.9 2009/09/30 19:50:22 tgl Exp $ */
-- Adjust this setting to control where the objects get dropped.
SET search_path = public;
DROP OPERATOR CLASS gist_hstore_ops USING gist CASCADE;
DROP OPERATOR CLASS gin_hstore_ops USING gin CASCADE;
DROP OPERATOR CLASS hash_hstore_ops USING hash CASCADE;
DROP OPERATOR CLASS btree_hstore_ops USING btree CASCADE;
DROP OPERATOR - ( hstore, text );
DROP OPERATOR - ( hstore, text[] );
DROP OPERATOR - ( hstore, hstore );
DROP OPERATOR ? ( hstore, text );
DROP OPERATOR ->( hstore, text );
DROP OPERATOR ||( hstore, hstore );
DROP OPERATOR @>( hstore, hstore );
DROP OPERATOR <@( hstore, hstore );
DROP OPERATOR @( hstore, hstore );
DROP OPERATOR ~( hstore, hstore );
DROP OPERATOR =>( text, text );
DROP OPERATOR ?& ( hstore, text[] );
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 );
DROP OPERATOR ~ ( hstore, hstore );
DROP OPERATOR => ( text, text );
DROP OPERATOR => ( text[], text[] );
DROP OPERATOR => ( hstore, text[] );
DROP OPERATOR #= ( anyelement, hstore );
DROP OPERATOR %% ( NONE, hstore );
DROP OPERATOR %# ( NONE, hstore );
DROP OPERATOR = ( hstore, hstore );
DROP OPERATOR <> ( hstore, hstore );
DROP OPERATOR #<# ( hstore, hstore );
DROP OPERATOR #<=# ( hstore, hstore );
DROP OPERATOR #># ( hstore, hstore );
DROP OPERATOR #>=# ( hstore, hstore );
DROP CAST (text[] AS hstore);
DROP FUNCTION hstore_eq(hstore,hstore);
DROP FUNCTION hstore_ne(hstore,hstore);
DROP FUNCTION hstore_gt(hstore,hstore);
DROP FUNCTION hstore_ge(hstore,hstore);
DROP FUNCTION hstore_lt(hstore,hstore);
DROP FUNCTION hstore_le(hstore,hstore);
DROP FUNCTION hstore_cmp(hstore,hstore);
DROP FUNCTION hstore_hash(hstore);
DROP FUNCTION slice_array(hstore,text[]);
DROP FUNCTION slice_hstore(hstore,text[]);
DROP FUNCTION fetchval(hstore,text);
DROP FUNCTION isexists(hstore,text);
DROP FUNCTION exist(hstore,text);
DROP FUNCTION exists_any(hstore,text[]);
DROP FUNCTION exists_all(hstore,text[]);
DROP FUNCTION isdefined(hstore,text);
DROP FUNCTION defined(hstore,text);
DROP FUNCTION delete(hstore,text);
DROP FUNCTION delete(hstore,text[]);
DROP FUNCTION delete(hstore,hstore);
DROP FUNCTION hs_concat(hstore,hstore);
DROP FUNCTION hs_contains(hstore,hstore);
DROP FUNCTION hs_contained(hstore,hstore);
DROP FUNCTION tconvert(text,text);
DROP FUNCTION hstore(text,text);
DROP FUNCTION hstore(text[],text[]);
DROP FUNCTION hstore_to_array(hstore);
DROP FUNCTION hstore_to_matrix(hstore);
DROP FUNCTION hstore(record);
DROP FUNCTION hstore(text[]);
DROP FUNCTION akeys(hstore);
DROP FUNCTION avals(hstore);
DROP FUNCTION skeys(hstore);
DROP FUNCTION svals(hstore);
DROP FUNCTION each(hstore);
DROP FUNCTION populate_record(anyelement,hstore);
DROP FUNCTION ghstore_compress(internal);
DROP FUNCTION ghstore_decompress(internal);
DROP FUNCTION ghstore_penalty(internal,internal,internal);
......@@ -41,6 +82,7 @@ DROP FUNCTION ghstore_consistent(internal,internal,int,oid,internal);
DROP FUNCTION gin_consistent_hstore(internal, int2, internal, int4, internal, internal);
DROP FUNCTION gin_extract_hstore(internal, internal);
DROP FUNCTION gin_extract_hstore_query(internal, internal, smallint, internal, internal);
DROP FUNCTION hstore_version_diag(hstore);
DROP TYPE hstore CASCADE;
DROP TYPE ghstore CASCADE;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment