2
* contrib/hstore/hstore_gin.c
6
#include "access/gin.h"
7
#include "access/skey.h"
8
#include "catalog/pg_type.h"
14
* When using a GIN index for hstore, we choose to index both keys and values.
15
* The storage format is "text" values, with K, V, or N prepended to the string
16
* to indicate key, value, or null values. (As of 9.1 it might be better to
17
* store null values as nulls, but we'll keep it this way for on-disk
24
PG_FUNCTION_INFO_V1(gin_extract_hstore);
25
Datum gin_extract_hstore(PG_FUNCTION_ARGS);
27
/* Build an indexable text value */
29
makeitem(char *str, int len, char flag)
33
item = (text *) palloc(VARHDRSZ + len + 1);
34
SET_VARSIZE(item, VARHDRSZ + len + 1);
36
*VARDATA(item) = flag;
39
memcpy(VARDATA(item) + 1, str, len);
45
gin_extract_hstore(PG_FUNCTION_ARGS)
47
HStore *hs = PG_GETARG_HS(0);
48
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
49
Datum *entries = NULL;
50
HEntry *hsent = ARRPTR(hs);
51
char *ptr = STRPTR(hs);
52
int count = HS_COUNT(hs);
55
*nentries = 2 * count;
57
entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
59
for (i = 0; i < count; ++i)
63
item = makeitem(HS_KEY(hsent, ptr, i), HS_KEYLEN(hsent, i),
65
entries[2 * i] = PointerGetDatum(item);
67
if (HS_VALISNULL(hsent, i))
68
item = makeitem(NULL, 0, NULLFLAG);
70
item = makeitem(HS_VAL(hsent, ptr, i), HS_VALLEN(hsent, i),
72
entries[2 * i + 1] = PointerGetDatum(item);
75
PG_RETURN_POINTER(entries);
78
PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
79
Datum gin_extract_hstore_query(PG_FUNCTION_ARGS);
82
gin_extract_hstore_query(PG_FUNCTION_ARGS)
84
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
85
StrategyNumber strategy = PG_GETARG_UINT16(2);
86
int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
89
if (strategy == HStoreContainsStrategyNumber)
91
/* Query is an hstore, so just apply gin_extract_hstore... */
93
DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
95
PointerGetDatum(nentries)));
96
/* ... except that "contains {}" requires a full index scan */
98
*searchMode = GIN_SEARCH_MODE_ALL;
100
else if (strategy == HStoreExistsStrategyNumber)
102
text *query = PG_GETARG_TEXT_PP(0);
106
entries = (Datum *) palloc(sizeof(Datum));
107
item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
108
entries[0] = PointerGetDatum(item);
110
else if (strategy == HStoreExistsAnyStrategyNumber ||
111
strategy == HStoreExistsAllStrategyNumber)
113
ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
121
deconstruct_array(query,
122
TEXTOID, -1, false, 'i',
123
&key_datums, &key_nulls, &key_count);
125
entries = (Datum *) palloc(sizeof(Datum) * key_count);
127
for (i = 0, j = 0; i < key_count; ++i)
129
/* Nulls in the array are ignored, cf hstoreArrayToPairs */
132
item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
133
entries[j++] = PointerGetDatum(item);
137
/* ExistsAll with no keys should match everything */
138
if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
139
*searchMode = GIN_SEARCH_MODE_ALL;
143
elog(ERROR, "unrecognized strategy number: %d", strategy);
144
entries = NULL; /* keep compiler quiet */
147
PG_RETURN_POINTER(entries);
150
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
151
Datum gin_consistent_hstore(PG_FUNCTION_ARGS);
154
gin_consistent_hstore(PG_FUNCTION_ARGS)
156
bool *check = (bool *) PG_GETARG_POINTER(0);
157
StrategyNumber strategy = PG_GETARG_UINT16(1);
159
/* HStore *query = PG_GETARG_HS(2); */
160
int32 nkeys = PG_GETARG_INT32(3);
162
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
163
bool *recheck = (bool *) PG_GETARG_POINTER(5);
167
if (strategy == HStoreContainsStrategyNumber)
170
* Index doesn't have information about correspondence of keys and
171
* values, so we need recheck. However, if not all the keys are
172
* present, we can fail at once.
175
for (i = 0; i < nkeys; i++)
184
else if (strategy == HStoreExistsStrategyNumber)
186
/* Existence of key is guaranteed in default search mode */
190
else if (strategy == HStoreExistsAnyStrategyNumber)
192
/* Existence of key is guaranteed in default search mode */
196
else if (strategy == HStoreExistsAllStrategyNumber)
198
/* Testing for all the keys being present gives an exact result */
200
for (i = 0; i < nkeys; i++)
210
elog(ERROR, "unrecognized strategy number: %d", strategy);