TLA Line data Source code
1 : /*
2 : * contrib/hstore/hstore_gist.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include "access/gist.h"
7 : #include "access/reloptions.h"
8 : #include "access/stratnum.h"
9 : #include "catalog/pg_type.h"
10 : #include "hstore.h"
11 : #include "utils/pg_crc.h"
12 :
13 : /* gist_hstore_ops opclass options */
14 : typedef struct
15 : {
16 : int32 vl_len_; /* varlena header (do not touch directly!) */
17 : int siglen; /* signature length in bytes */
18 : } GistHstoreOptions;
19 :
20 : /* bigint defines */
21 : #define BITBYTE 8
22 : #define SIGLEN_DEFAULT (sizeof(int32) * 4)
23 : #define SIGLEN_MAX GISTMaxIndexKeySize
24 : #define SIGLENBIT(siglen) ((siglen) * BITBYTE)
25 : #define GET_SIGLEN() (PG_HAS_OPCLASS_OPTIONS() ? \
26 : ((GistHstoreOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
27 : SIGLEN_DEFAULT)
28 :
29 :
30 : typedef char *BITVECP;
31 :
32 : #define LOOPBYTE(siglen) \
33 : for (i = 0; i < (siglen); i++)
34 :
35 : #define LOOPBIT(siglen) \
36 : for (i = 0; i < SIGLENBIT(siglen); i++)
37 :
38 : /* beware of multiple evaluation of arguments to these macros! */
39 : #define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
40 : #define GETBITBYTE(x,i) ( (*((char*)(x)) >> (i)) & 0x01 )
41 : #define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) )
42 : #define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITBYTE ) )
43 : #define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 )
44 : #define HASHVAL(val, siglen) (((unsigned int)(val)) % SIGLENBIT(siglen))
45 : #define HASH(sign, val, siglen) SETBIT((sign), HASHVAL(val, siglen))
46 :
47 : typedef struct
48 : {
49 : int32 vl_len_; /* varlena header (do not touch directly!) */
50 : int32 flag;
51 : char data[FLEXIBLE_ARRAY_MEMBER];
52 : } GISTTYPE;
53 :
54 : #define ALLISTRUE 0x04
55 :
56 : #define ISALLTRUE(x) ( ((GISTTYPE*)x)->flag & ALLISTRUE )
57 :
58 : #define GTHDRSIZE (VARHDRSZ + sizeof(int32))
59 : #define CALCGTSIZE(flag, siglen) ( GTHDRSIZE+(((flag) & ALLISTRUE) ? 0 : (siglen)) )
60 :
61 : #define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
62 :
63 : #define SUMBIT(val) ( \
64 : GETBITBYTE((val),0) + \
65 : GETBITBYTE((val),1) + \
66 : GETBITBYTE((val),2) + \
67 : GETBITBYTE((val),3) + \
68 : GETBITBYTE((val),4) + \
69 : GETBITBYTE((val),5) + \
70 : GETBITBYTE((val),6) + \
71 : GETBITBYTE((val),7) \
72 : )
73 :
74 : #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
75 :
76 : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
77 :
78 : /* shorthand for calculating CRC-32 of a single chunk of data. */
79 : static pg_crc32
80 CBC 33062 : crc32_sz(char *buf, int size)
81 : {
82 : pg_crc32 crc;
83 :
84 33062 : INIT_TRADITIONAL_CRC32(crc);
85 176322 : COMP_TRADITIONAL_CRC32(crc, buf, size);
86 33062 : FIN_TRADITIONAL_CRC32(crc);
87 :
88 33062 : return crc;
89 : }
90 :
91 :
92 7 : PG_FUNCTION_INFO_V1(ghstore_in);
93 7 : PG_FUNCTION_INFO_V1(ghstore_out);
94 :
95 :
96 : Datum
97 UBC 0 : ghstore_in(PG_FUNCTION_ARGS)
98 : {
99 UNC 0 : ereport(ERROR,
100 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
101 : errmsg("cannot accept a value of type %s", "ghstore")));
102 :
103 : PG_RETURN_VOID(); /* keep compiler quiet */
104 : }
105 :
106 : Datum
107 UIC 0 : ghstore_out(PG_FUNCTION_ARGS)
108 : {
109 UNC 0 : ereport(ERROR,
110 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
111 : errmsg("cannot display a value of type %s", "ghstore")));
112 :
113 : PG_RETURN_VOID(); /* keep compiler quiet */
114 : }
115 EUB :
116 : static GISTTYPE *
117 GIC 9475 : ghstore_alloc(bool allistrue, int siglen, BITVECP sign)
118 : {
119 9475 : int flag = allistrue ? ALLISTRUE : 0;
120 9475 : int size = CALCGTSIZE(flag, siglen);
121 9475 : GISTTYPE *res = palloc(size);
122 :
123 CBC 9475 : SET_VARSIZE(res, size);
124 GIC 9475 : res->flag = flag;
125 ECB :
126 CBC 9475 : if (!allistrue)
127 ECB : {
128 GIC 9475 : if (sign)
129 CBC 1314 : memcpy(GETSIGN(res), sign, siglen);
130 ECB : else
131 GIC 8161 : memset(GETSIGN(res), 0, siglen);
132 ECB : }
133 :
134 CBC 9475 : return res;
135 ECB : }
136 :
137 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_consistent);
138 GIC 8 : PG_FUNCTION_INFO_V1(ghstore_compress);
139 8 : PG_FUNCTION_INFO_V1(ghstore_decompress);
140 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_penalty);
141 GIC 8 : PG_FUNCTION_INFO_V1(ghstore_picksplit);
142 8 : PG_FUNCTION_INFO_V1(ghstore_union);
143 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_same);
144 8 : PG_FUNCTION_INFO_V1(ghstore_options);
145 ECB :
146 : Datum
147 CBC 8142 : ghstore_compress(PG_FUNCTION_ARGS)
148 ECB : {
149 CBC 8142 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
150 8142 : int siglen = GET_SIGLEN();
151 GIC 8142 : GISTENTRY *retval = entry;
152 :
153 CBC 8142 : if (entry->leafkey)
154 : {
155 2002 : GISTTYPE *res = ghstore_alloc(false, siglen, NULL);
156 2002 : HStore *val = DatumGetHStoreP(entry->key);
157 2002 : HEntry *hsent = ARRPTR(val);
158 GIC 2002 : char *ptr = STRPTR(val);
159 CBC 2002 : int count = HS_COUNT(val);
160 : int i;
161 ECB :
162 CBC 11564 : for (i = 0; i < count; ++i)
163 ECB : {
164 : int h;
165 :
166 GIC 9562 : h = crc32_sz((char *) HSTORE_KEY(hsent, ptr, i),
167 9562 : HSTORE_KEYLEN(hsent, i));
168 CBC 9562 : HASH(GETSIGN(res), h, siglen);
169 GIC 9562 : if (!HSTORE_VALISNULL(hsent, i))
170 : {
171 9560 : h = crc32_sz((char *) HSTORE_VAL(hsent, ptr, i),
172 CBC 9560 : HSTORE_VALLEN(hsent, i));
173 9560 : HASH(GETSIGN(res), h, siglen);
174 ECB : }
175 : }
176 :
177 CBC 2002 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
178 2002 : gistentryinit(*retval, PointerGetDatum(res),
179 ECB : entry->rel, entry->page,
180 : entry->offset,
181 : false);
182 : }
183 CBC 6140 : else if (!ISALLTRUE(DatumGetPointer(entry->key)))
184 ECB : {
185 : int32 i;
186 : GISTTYPE *res;
187 GIC 6140 : BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
188 :
189 CBC 6140 : LOOPBYTE(siglen)
190 : {
191 GIC 6140 : if ((sign[i] & 0xff) != 0xff)
192 6140 : PG_RETURN_POINTER(retval);
193 ECB : }
194 :
195 LBC 0 : res = ghstore_alloc(true, siglen, NULL);
196 :
197 0 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
198 0 : gistentryinit(*retval, PointerGetDatum(res),
199 : entry->rel, entry->page,
200 : entry->offset,
201 EUB : false);
202 : }
203 :
204 GBC 2002 : PG_RETURN_POINTER(retval);
205 : }
206 :
207 : /*
208 : * Since type ghstore isn't toastable (and doesn't need to be),
209 : * this function can be a no-op.
210 ECB : */
211 : Datum
212 GIC 48666 : ghstore_decompress(PG_FUNCTION_ARGS)
213 : {
214 48666 : PG_RETURN_POINTER(PG_GETARG_POINTER(0));
215 : }
216 :
217 : Datum
218 CBC 6159 : ghstore_same(PG_FUNCTION_ARGS)
219 : {
220 6159 : GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
221 GIC 6159 : GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
222 6159 : bool *result = (bool *) PG_GETARG_POINTER(2);
223 6159 : int siglen = GET_SIGLEN();
224 ECB :
225 :
226 CBC 6159 : if (ISALLTRUE(a) && ISALLTRUE(b))
227 LBC 0 : *result = true;
228 CBC 6159 : else if (ISALLTRUE(a))
229 LBC 0 : *result = false;
230 GIC 6159 : else if (ISALLTRUE(b))
231 UIC 0 : *result = false;
232 ECB : else
233 EUB : {
234 ECB : int32 i;
235 GBC 6159 : BITVECP sa = GETSIGN(a),
236 CBC 6159 : sb = GETSIGN(b);
237 EUB :
238 GIC 6159 : *result = true;
239 4565619 : LOOPBYTE(siglen)
240 : {
241 CBC 4564286 : if (sa[i] != sb[i])
242 ECB : {
243 GIC 4826 : *result = false;
244 CBC 4826 : break;
245 ECB : }
246 : }
247 : }
248 GIC 6159 : PG_RETURN_POINTER(result);
249 ECB : }
250 :
251 : static int32
252 UIC 0 : sizebitvec(BITVECP sign, int siglen)
253 : {
254 LBC 0 : int32 size = 0,
255 : i;
256 :
257 UIC 0 : LOOPBYTE(siglen)
258 EUB : {
259 UIC 0 : size += SUMBIT(sign);
260 UBC 0 : sign = (BITVECP) (((char *) sign) + 1);
261 : }
262 UIC 0 : return size;
263 EUB : }
264 :
265 : static int
266 GBC 132428 : hemdistsign(BITVECP a, BITVECP b, int siglen)
267 : {
268 EUB : int i,
269 GIC 132428 : dist = 0;
270 :
271 383229964 : LOOPBIT(siglen)
272 ECB : {
273 GIC 383097536 : if (GETBIT(a, i) != GETBIT(b, i))
274 3347577 : dist++;
275 ECB : }
276 GIC 132428 : return dist;
277 ECB : }
278 :
279 : static int
280 CBC 132428 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
281 : {
282 132428 : if (ISALLTRUE(a))
283 : {
284 UIC 0 : if (ISALLTRUE(b))
285 0 : return 0;
286 ECB : else
287 UIC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
288 ECB : }
289 GIC 132428 : else if (ISALLTRUE(b))
290 UBC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
291 EUB :
292 GIC 132428 : return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
293 EUB : }
294 :
295 ECB : static int32
296 GBC 12318 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
297 : {
298 ECB : int32 i;
299 GIC 12318 : BITVECP sadd = GETSIGN(add);
300 :
301 12318 : if (ISALLTRUE(add))
302 LBC 0 : return 1;
303 GIC 21743198 : LOOPBYTE(siglen)
304 21730880 : sbase[i] |= sadd[i];
305 CBC 12318 : return 0;
306 : }
307 ECB :
308 EUB : Datum
309 CBC 6159 : ghstore_union(PG_FUNCTION_ARGS)
310 ECB : {
311 CBC 6159 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
312 GIC 6159 : int32 len = entryvec->n;
313 :
314 6159 : int *size = (int *) PG_GETARG_POINTER(1);
315 CBC 6159 : int siglen = GET_SIGLEN();
316 : int32 i;
317 6159 : GISTTYPE *result = ghstore_alloc(false, siglen, NULL);
318 6159 : BITVECP base = GETSIGN(result);
319 :
320 18477 : for (i = 0; i < len; i++)
321 ECB : {
322 GIC 12318 : if (unionkey(base, GETENTRY(entryvec, i), siglen))
323 ECB : {
324 LBC 0 : result->flag |= ALLISTRUE;
325 UIC 0 : SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
326 LBC 0 : break;
327 : }
328 ECB : }
329 :
330 GBC 6159 : *size = VARSIZE(result);
331 EUB :
332 GBC 6159 : PG_RETURN_POINTER(result);
333 : }
334 :
335 : Datum
336 CBC 16073 : ghstore_penalty(PG_FUNCTION_ARGS)
337 : {
338 16073 : GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
339 GIC 16073 : GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
340 16073 : float *penalty = (float *) PG_GETARG_POINTER(2);
341 16073 : int siglen = GET_SIGLEN();
342 CBC 16073 : GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
343 GIC 16073 : GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
344 ECB :
345 CBC 16073 : *penalty = hemdist(origval, newval, siglen);
346 16073 : PG_RETURN_POINTER(penalty);
347 ECB : }
348 :
349 :
350 : typedef struct
351 : {
352 : OffsetNumber pos;
353 : int32 cost;
354 : } SPLITCOST;
355 :
356 : static int
357 GIC 5946 : comparecost(const void *a, const void *b)
358 : {
359 5946 : return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
360 : }
361 :
362 :
363 ECB : Datum
364 GIC 657 : ghstore_picksplit(PG_FUNCTION_ARGS)
365 ECB : {
366 GIC 657 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
367 657 : OffsetNumber maxoff = entryvec->n - 2;
368 :
369 657 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
370 CBC 657 : int siglen = GET_SIGLEN();
371 : OffsetNumber k,
372 ECB : j;
373 : GISTTYPE *datum_l,
374 : *datum_r;
375 : BITVECP union_l,
376 : union_r;
377 : int32 size_alpha,
378 : size_beta;
379 : int32 size_waste,
380 GIC 657 : waste = -1;
381 : int32 nbytes;
382 657 : OffsetNumber seed_1 = 0,
383 657 : seed_2 = 0;
384 : OffsetNumber *left,
385 : *right;
386 ECB : BITVECP ptr;
387 : int i;
388 : SPLITCOST *costvector;
389 : GISTTYPE *_k,
390 : *_j;
391 :
392 GIC 657 : nbytes = (maxoff + 2) * sizeof(OffsetNumber);
393 657 : v->spl_left = (OffsetNumber *) palloc(nbytes);
394 657 : v->spl_right = (OffsetNumber *) palloc(nbytes);
395 :
396 2971 : for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
397 : {
398 CBC 2314 : _k = GETENTRY(entryvec, k);
399 106785 : for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
400 ECB : {
401 GIC 104471 : size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
402 CBC 104471 : if (size_waste > waste)
403 : {
404 1089 : waste = size_waste;
405 1089 : seed_1 = k;
406 GIC 1089 : seed_2 = j;
407 ECB : }
408 : }
409 : }
410 :
411 CBC 657 : left = v->spl_left;
412 657 : v->spl_nleft = 0;
413 GIC 657 : right = v->spl_right;
414 657 : v->spl_nright = 0;
415 :
416 657 : if (seed_1 == 0 || seed_2 == 0)
417 ECB : {
418 LBC 0 : seed_1 = 1;
419 0 : seed_2 = 2;
420 ECB : }
421 :
422 : /* form initial .. */
423 GIC 657 : datum_l = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
424 GBC 657 : GETSIGN(GETENTRY(entryvec, seed_1)));
425 657 : datum_r = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
426 GIC 657 : GETSIGN(GETENTRY(entryvec, seed_2)));
427 :
428 657 : maxoff = OffsetNumberNext(maxoff);
429 ECB : /* sort before ... */
430 CBC 657 : costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
431 4285 : for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
432 ECB : {
433 GIC 3628 : costvector[j - 1].pos = j;
434 CBC 3628 : _j = GETENTRY(entryvec, j);
435 GIC 3628 : size_alpha = hemdist(datum_l, _j, siglen);
436 CBC 3628 : size_beta = hemdist(datum_r, _j, siglen);
437 3628 : costvector[j - 1].cost = abs(size_alpha - size_beta);
438 : }
439 GNC 657 : qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
440 ECB :
441 CBC 657 : union_l = GETSIGN(datum_l);
442 657 : union_r = GETSIGN(datum_r);
443 ECB :
444 GIC 4285 : for (k = 0; k < maxoff; k++)
445 ECB : {
446 GIC 3628 : j = costvector[k].pos;
447 CBC 3628 : if (j == seed_1)
448 ECB : {
449 GIC 657 : *left++ = j;
450 CBC 657 : v->spl_nleft++;
451 GIC 657 : continue;
452 ECB : }
453 CBC 2971 : else if (j == seed_2)
454 : {
455 657 : *right++ = j;
456 657 : v->spl_nright++;
457 657 : continue;
458 : }
459 2314 : _j = GETENTRY(entryvec, j);
460 GIC 2314 : size_alpha = hemdist(datum_l, _j, siglen);
461 CBC 2314 : size_beta = hemdist(datum_r, _j, siglen);
462 ECB :
463 CBC 2314 : if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.0001))
464 : {
465 1126 : if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
466 ECB : {
467 LBC 0 : if (!ISALLTRUE(datum_l))
468 UNC 0 : memset(union_l, 0xff, siglen);
469 ECB : }
470 : else
471 : {
472 GIC 1126 : ptr = GETSIGN(_j);
473 GBC 1278158 : LOOPBYTE(siglen)
474 1277032 : union_l[i] |= ptr[i];
475 : }
476 GIC 1126 : *left++ = j;
477 1126 : v->spl_nleft++;
478 ECB : }
479 : else
480 : {
481 GIC 1188 : if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
482 ECB : {
483 LBC 0 : if (!ISALLTRUE(datum_r))
484 UNC 0 : memset(union_r, 0xff, siglen);
485 : }
486 : else
487 ECB : {
488 GIC 1188 : ptr = GETSIGN(_j);
489 GBC 1379612 : LOOPBYTE(siglen)
490 1378424 : union_r[i] |= ptr[i];
491 : }
492 GIC 1188 : *right++ = j;
493 1188 : v->spl_nright++;
494 ECB : }
495 : }
496 :
497 GIC 657 : *right = *left = FirstOffsetNumber;
498 ECB :
499 CBC 657 : v->spl_ldatum = PointerGetDatum(datum_l);
500 GIC 657 : v->spl_rdatum = PointerGetDatum(datum_r);
501 :
502 657 : PG_RETURN_POINTER(v);
503 ECB : }
504 :
505 :
506 : Datum
507 GIC 10488 : ghstore_consistent(PG_FUNCTION_ARGS)
508 ECB : {
509 GIC 10488 : GISTTYPE *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
510 10488 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
511 :
512 : /* Oid subtype = PG_GETARG_OID(3); */
513 CBC 10488 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
514 GIC 10488 : int siglen = GET_SIGLEN();
515 CBC 10488 : bool res = true;
516 ECB : BITVECP sign;
517 :
518 : /* All cases served by this function are inexact */
519 CBC 10488 : *recheck = true;
520 ECB :
521 CBC 10488 : if (ISALLTRUE(entry))
522 UIC 0 : PG_RETURN_BOOL(true);
523 :
524 GIC 10488 : sign = GETSIGN(entry);
525 ECB :
526 GIC 10488 : if (strategy == HStoreContainsStrategyNumber ||
527 ECB : strategy == HStoreOldContainsStrategyNumber)
528 GBC 4691 : {
529 GIC 4691 : HStore *query = PG_GETARG_HSTORE_P(1);
530 CBC 4691 : HEntry *qe = ARRPTR(query);
531 GIC 4691 : char *qv = STRPTR(query);
532 CBC 4691 : int count = HS_COUNT(query);
533 : int i;
534 ECB :
535 CBC 9589 : for (i = 0; res && i < count; ++i)
536 ECB : {
537 CBC 4898 : int crc = crc32_sz((char *) HSTORE_KEY(qe, qv, i),
538 4898 : HSTORE_KEYLEN(qe, i));
539 :
540 GIC 4898 : if (GETBIT(sign, HASHVAL(crc, siglen)))
541 ECB : {
542 GIC 1961 : if (!HSTORE_VALISNULL(qe, i))
543 ECB : {
544 CBC 1170 : crc = crc32_sz((char *) HSTORE_VAL(qe, qv, i),
545 GIC 1170 : HSTORE_VALLEN(qe, i));
546 CBC 1170 : if (!GETBIT(sign, HASHVAL(crc, siglen)))
547 GIC 583 : res = false;
548 ECB : }
549 : }
550 : else
551 CBC 2937 : res = false;
552 ECB : }
553 : }
554 GIC 5797 : else if (strategy == HStoreExistsStrategyNumber)
555 : {
556 1939 : text *query = PG_GETARG_TEXT_PP(1);
557 CBC 1939 : int crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
558 :
559 GIC 1939 : res = (GETBIT(sign, HASHVAL(crc, siglen))) ? true : false;
560 ECB : }
561 GIC 3858 : else if (strategy == HStoreExistsAllStrategyNumber)
562 ECB : {
563 CBC 1622 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
564 : Datum *key_datums;
565 ECB : bool *key_nulls;
566 : int key_count;
567 : int i;
568 :
569 GNC 1622 : deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
570 :
571 GIC 3875 : for (i = 0; res && i < key_count; ++i)
572 : {
573 ECB : int crc;
574 :
575 CBC 2253 : if (key_nulls[i])
576 UIC 0 : continue;
577 GIC 2253 : crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
578 2253 : if (!(GETBIT(sign, HASHVAL(crc, siglen))))
579 CBC 1297 : res = false;
580 EUB : }
581 ECB : }
582 CBC 2236 : else if (strategy == HStoreExistsAnyStrategyNumber)
583 ECB : {
584 GIC 2236 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
585 : Datum *key_datums;
586 ECB : bool *key_nulls;
587 : int key_count;
588 : int i;
589 :
590 GNC 2236 : deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
591 :
592 CBC 2236 : res = false;
593 :
594 5916 : for (i = 0; !res && i < key_count; ++i)
595 : {
596 ECB : int crc;
597 :
598 GIC 3680 : if (key_nulls[i])
599 UIC 0 : continue;
600 CBC 3680 : crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
601 GBC 3680 : if (GETBIT(sign, HASHVAL(crc, siglen)))
602 CBC 1201 : res = true;
603 ECB : }
604 : }
605 : else
606 UIC 0 : elog(ERROR, "Unsupported strategy number: %d", strategy);
607 :
608 GBC 10488 : PG_RETURN_BOOL(res);
609 : }
610 ECB :
611 : Datum
612 GIC 9 : ghstore_options(PG_FUNCTION_ARGS)
613 : {
614 CBC 9 : local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
615 :
616 9 : init_local_reloptions(relopts, sizeof(GistHstoreOptions));
617 GIC 9 : add_local_int_reloption(relopts, "siglen",
618 ECB : "signature length in bytes",
619 : SIGLEN_DEFAULT, 1, SIGLEN_MAX,
620 : offsetof(GistHstoreOptions, siglen));
621 :
622 GIC 9 : PG_RETURN_VOID();
623 : }
|