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