PostgreSQL Source Code git master
hstore_gin.c
Go to the documentation of this file.
1/*
2 * contrib/hstore/hstore_gin.c
3 */
4#include "postgres.h"
5
6#include "access/gin.h"
7#include "access/stratnum.h"
8#include "catalog/pg_type.h"
9
10#include "hstore.h"
11
12
13/*
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
18 * compatibility.)
19 */
20#define KEYFLAG 'K'
21#define VALFLAG 'V'
22#define NULLFLAG 'N'
23
25
26/* Build an indexable text value */
27static text *
28makeitem(char *str, int len, char flag)
29{
30 text *item;
31
32 item = (text *) palloc(VARHDRSZ + len + 1);
33 SET_VARSIZE(item, VARHDRSZ + len + 1);
34
35 *VARDATA(item) = flag;
36
37 if (str && len > 0)
38 memcpy(VARDATA(item) + 1, str, len);
39
40 return item;
41}
42
45{
47 int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
48 Datum *entries = NULL;
49 HEntry *hsent = ARRPTR(hs);
50 char *ptr = STRPTR(hs);
51 int count = HS_COUNT(hs);
52 int i;
53
54 *nentries = 2 * count;
55 if (count)
56 entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
57
58 for (i = 0; i < count; ++i)
59 {
60 text *item;
61
62 item = makeitem(HSTORE_KEY(hsent, ptr, i),
63 HSTORE_KEYLEN(hsent, i),
64 KEYFLAG);
65 entries[2 * i] = PointerGetDatum(item);
66
67 if (HSTORE_VALISNULL(hsent, i))
68 item = makeitem(NULL, 0, NULLFLAG);
69 else
70 item = makeitem(HSTORE_VAL(hsent, ptr, i),
71 HSTORE_VALLEN(hsent, i),
72 VALFLAG);
73 entries[2 * i + 1] = PointerGetDatum(item);
74 }
75
76 PG_RETURN_POINTER(entries);
77}
78
80
83{
84 int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
85 StrategyNumber strategy = PG_GETARG_UINT16(2);
86 int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
87 Datum *entries;
88
89 if (strategy == HStoreContainsStrategyNumber)
90 {
91 /* Query is an hstore, so just apply gin_extract_hstore... */
92 entries = (Datum *)
95 PointerGetDatum(nentries)));
96 /* ... except that "contains {}" requires a full index scan */
97 if (entries == NULL)
98 *searchMode = GIN_SEARCH_MODE_ALL;
99 }
100 else if (strategy == HStoreExistsStrategyNumber)
101 {
102 text *query = PG_GETARG_TEXT_PP(0);
103 text *item;
104
105 *nentries = 1;
106 entries = (Datum *) palloc(sizeof(Datum));
107 item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
108 entries[0] = PointerGetDatum(item);
109 }
110 else if (strategy == HStoreExistsAnyStrategyNumber ||
112 {
114 Datum *key_datums;
115 bool *key_nulls;
116 int key_count;
117 int i,
118 j;
119 text *item;
120
121 deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
122
123 entries = (Datum *) palloc(sizeof(Datum) * key_count);
124
125 for (i = 0, j = 0; i < key_count; ++i)
126 {
127 /* Nulls in the array are ignored, cf hstoreArrayToPairs */
128 if (key_nulls[i])
129 continue;
130 item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
131 entries[j++] = PointerGetDatum(item);
132 }
133
134 *nentries = j;
135 /* ExistsAll with no keys should match everything */
136 if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
137 *searchMode = GIN_SEARCH_MODE_ALL;
138 }
139 else
140 {
141 elog(ERROR, "unrecognized strategy number: %d", strategy);
142 entries = NULL; /* keep compiler quiet */
143 }
144
145 PG_RETURN_POINTER(entries);
146}
147
149
150Datum
152{
153 bool *check = (bool *) PG_GETARG_POINTER(0);
154 StrategyNumber strategy = PG_GETARG_UINT16(1);
155
156 /* HStore *query = PG_GETARG_HSTORE_P(2); */
157 int32 nkeys = PG_GETARG_INT32(3);
158
159 /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
160 bool *recheck = (bool *) PG_GETARG_POINTER(5);
161 bool res = true;
162 int32 i;
163
164 if (strategy == HStoreContainsStrategyNumber)
165 {
166 /*
167 * Index doesn't have information about correspondence of keys and
168 * values, so we need recheck. However, if not all the keys are
169 * present, we can fail at once.
170 */
171 *recheck = true;
172 for (i = 0; i < nkeys; i++)
173 {
174 if (!check[i])
175 {
176 res = false;
177 break;
178 }
179 }
180 }
181 else if (strategy == HStoreExistsStrategyNumber)
182 {
183 /* Existence of key is guaranteed in default search mode */
184 *recheck = false;
185 res = true;
186 }
187 else if (strategy == HStoreExistsAnyStrategyNumber)
188 {
189 /* Existence of key is guaranteed in default search mode */
190 *recheck = false;
191 res = true;
192 }
193 else if (strategy == HStoreExistsAllStrategyNumber)
194 {
195 /* Testing for all the keys being present gives an exact result */
196 *recheck = false;
197 for (i = 0; i < nkeys; i++)
198 {
199 if (!check[i])
200 {
201 res = false;
202 break;
203 }
204 }
205 }
206 else
207 elog(ERROR, "unrecognized strategy number: %d", strategy);
208
209 PG_RETURN_BOOL(res);
210}
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
#define VARHDRSZ
Definition: c.h:663
int32_t int32
Definition: c.h:498
#define ARRPTR(x)
Definition: cube.c:25
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:38
const char * str
#define HStoreExistsAllStrategyNumber
Definition: hstore.h:183
#define HStoreExistsStrategyNumber
Definition: hstore.h:181
#define HS_COUNT(hsp_)
Definition: hstore.h:61
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
#define PG_GETARG_HSTORE_P(x)
Definition: hstore.h:154
#define HStoreExistsAnyStrategyNumber
Definition: hstore.h:182
#define HStoreContainsStrategyNumber
Definition: hstore.h:180
#define HSTORE_VALISNULL(arr_, i_)
Definition: hstore.h:83
#define HSTORE_VALLEN(arr_, i_)
Definition: hstore.h:82
#define HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
#define HSTORE_VAL(arr_, str_, i_)
Definition: hstore.h:80
#define STRPTR(x)
Definition: hstore.h:76
static text * makeitem(char *str, int len, char flag)
Definition: hstore_gin.c:28
#define VALFLAG
Definition: hstore_gin.c:21
Datum gin_consistent_hstore(PG_FUNCTION_ARGS)
Definition: hstore_gin.c:151
Datum gin_extract_hstore_query(PG_FUNCTION_ARGS)
Definition: hstore_gin.c:82
PG_FUNCTION_INFO_V1(gin_extract_hstore)
#define NULLFLAG
Definition: hstore_gin.c:22
Datum gin_extract_hstore(PG_FUNCTION_ARGS)
Definition: hstore_gin.c:44
#define KEYFLAG
Definition: hstore_gin.c:20
int j
Definition: isn.c:75
int i
Definition: isn.c:74
void * palloc(Size size)
Definition: mcxt.c:1317
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
uint16 StrategyNumber
Definition: stratnum.h:22
Definition: hstore.h:19
Definition: hstore.h:45
Definition: c.h:658
char * flag(int b)
Definition: test-ctype.c:33
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317