summaryrefslogtreecommitdiff
path: root/contrib/hstore/hstore_gist.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-09-30 19:50:22 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-09-30 19:50:22 +0000
commit172eacba43417c31e5eb61a5ae7a6aaca7a25928 (patch)
treed8b14cfac15b4f5e34a64deb7baa710a8e5e2bd4 /contrib/hstore/hstore_gist.c
parent1d43e5314e30bbd10f51e4c740ab4814775375b0 (diff)
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
Diffstat (limited to 'contrib/hstore/hstore_gist.c')
-rw-r--r--contrib/hstore/hstore_gist.c96
1 files changed, 70 insertions, 26 deletions
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index 0f6eac347c7..b036fa932f2 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -1,13 +1,14 @@
/*
- * $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;
+ 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);