/* * $PostgreSQL: pgsql/contrib/hstore/hstore_gin.c,v 1.4 2008/05/12 00:00:42 alvherre Exp $ */ #include "postgres.h" #include "access/gin.h" #include "hstore.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) { bool *check = (bool *) PG_GETARG_POINTER(0); StrategyNumber strategy = PG_GETARG_UINT16(1); HStore *query = PG_GETARG_HS(2); bool *recheck = (bool *) PG_GETARG_POINTER(3); bool res = true; if (strategy == HStoreContainsStrategyNumber) { int i; /* * Index lost information about correspondence of keys * and values, so we need recheck */ *recheck = true; for (i = 0; res && i < 2 * query->size; i++) if (check[i] == false) res = false; } else if (strategy == HStoreExistsStrategyNumber) { /* Existence of key is guaranteed */ *recheck = false; res = true; } else elog(ERROR, "Unsupported strategy number: %d", strategy); PG_RETURN_BOOL(res); }