Age Owner 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
3078 heikki.linnakangas 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 :
6060 teodor 92 7 : PG_FUNCTION_INFO_V1(ghstore_in);
93 7 : PG_FUNCTION_INFO_V1(ghstore_out);
94 :
95 :
96 : Datum
6031 bruce 97 UBC 0 : ghstore_in(PG_FUNCTION_ARGS)
98 : {
120 tgl 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
6031 bruce 107 UIC 0 : ghstore_out(PG_FUNCTION_ARGS)
108 : {
120 tgl 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 : }
6060 teodor 115 EUB :
116 : static GISTTYPE *
1105 akorotkov 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 :
1105 akorotkov 123 CBC 9475 : SET_VARSIZE(res, size);
1105 akorotkov 124 GIC 9475 : res->flag = flag;
1105 akorotkov 125 ECB :
1105 akorotkov 126 CBC 9475 : if (!allistrue)
1105 akorotkov 127 ECB : {
1105 akorotkov 128 GIC 9475 : if (sign)
1105 akorotkov 129 CBC 1314 : memcpy(GETSIGN(res), sign, siglen);
1105 akorotkov 130 ECB : else
1105 akorotkov 131 GIC 8161 : memset(GETSIGN(res), 0, siglen);
1105 akorotkov 132 ECB : }
133 :
1105 akorotkov 134 CBC 9475 : return res;
1105 akorotkov 135 ECB : }
136 :
6060 teodor 137 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_consistent);
6060 teodor 138 GIC 8 : PG_FUNCTION_INFO_V1(ghstore_compress);
139 8 : PG_FUNCTION_INFO_V1(ghstore_decompress);
6060 teodor 140 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_penalty);
6060 teodor 141 GIC 8 : PG_FUNCTION_INFO_V1(ghstore_picksplit);
142 8 : PG_FUNCTION_INFO_V1(ghstore_union);
6060 teodor 143 CBC 8 : PG_FUNCTION_INFO_V1(ghstore_same);
1105 akorotkov 144 8 : PG_FUNCTION_INFO_V1(ghstore_options);
6060 teodor 145 ECB :
146 : Datum
6031 bruce 147 CBC 8142 : ghstore_compress(PG_FUNCTION_ARGS)
6031 bruce 148 ECB : {
6060 teodor 149 CBC 8142 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1105 akorotkov 150 8142 : int siglen = GET_SIGLEN();
6060 teodor 151 GIC 8142 : GISTENTRY *retval = entry;
152 :
6031 bruce 153 CBC 8142 : if (entry->leafkey)
154 : {
1105 akorotkov 155 2002 : GISTTYPE *res = ghstore_alloc(false, siglen, NULL);
4939 tgl 156 2002 : HStore *val = DatumGetHStoreP(entry->key);
157 2002 : HEntry *hsent = ARRPTR(val);
4939 tgl 158 GIC 2002 : char *ptr = STRPTR(val);
4790 bruce 159 CBC 2002 : int count = HS_COUNT(val);
160 : int i;
6031 bruce 161 ECB :
4939 tgl 162 CBC 11564 : for (i = 0; i < count; ++i)
6031 bruce 163 ECB : {
4790 164 : int h;
6031 165 :
2698 tgl 166 GIC 9562 : h = crc32_sz((char *) HSTORE_KEY(hsent, ptr, i),
167 9562 : HSTORE_KEYLEN(hsent, i));
1105 akorotkov 168 CBC 9562 : HASH(GETSIGN(res), h, siglen);
2698 tgl 169 GIC 9562 : if (!HSTORE_VALISNULL(hsent, i))
170 : {
171 9560 : h = crc32_sz((char *) HSTORE_VAL(hsent, ptr, i),
2698 tgl 172 CBC 9560 : HSTORE_VALLEN(hsent, i));
1105 akorotkov 173 9560 : HASH(GETSIGN(res), h, siglen);
6060 teodor 174 ECB : }
175 : }
176 :
6060 teodor 177 CBC 2002 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
178 2002 : gistentryinit(*retval, PointerGetDatum(res),
6060 teodor 179 ECB : entry->rel, entry->page,
180 : entry->offset,
181 : false);
182 : }
6031 bruce 183 CBC 6140 : else if (!ISALLTRUE(DatumGetPointer(entry->key)))
6031 bruce 184 ECB : {
185 : int32 i;
186 : GISTTYPE *res;
6031 bruce 187 GIC 6140 : BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
188 :
1105 akorotkov 189 CBC 6140 : LOOPBYTE(siglen)
190 : {
5623 bruce 191 GIC 6140 : if ((sign[i] & 0xff) != 0xff)
192 6140 : PG_RETURN_POINTER(retval);
5623 bruce 193 ECB : }
194 :
1105 akorotkov 195 LBC 0 : res = ghstore_alloc(true, siglen, NULL);
196 :
6060 teodor 197 0 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
198 0 : gistentryinit(*retval, PointerGetDatum(res),
199 : entry->rel, entry->page,
200 : entry->offset,
2062 peter_e 201 EUB : false);
202 : }
6060 teodor 203 :
6060 teodor 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.
4588 tgl 210 ECB : */
211 : Datum
6031 bruce 212 GIC 48666 : ghstore_decompress(PG_FUNCTION_ARGS)
213 : {
4588 tgl 214 48666 : PG_RETURN_POINTER(PG_GETARG_POINTER(0));
215 : }
216 :
217 : Datum
6031 bruce 218 CBC 6159 : ghstore_same(PG_FUNCTION_ARGS)
219 : {
6060 teodor 220 6159 : GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
6060 teodor 221 GIC 6159 : GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
6031 bruce 222 6159 : bool *result = (bool *) PG_GETARG_POINTER(2);
1105 akorotkov 223 6159 : int siglen = GET_SIGLEN();
1105 akorotkov 224 ECB :
225 :
6060 teodor 226 CBC 6159 : if (ISALLTRUE(a) && ISALLTRUE(b))
6060 teodor 227 LBC 0 : *result = true;
6060 teodor 228 CBC 6159 : else if (ISALLTRUE(a))
6060 teodor 229 LBC 0 : *result = false;
6060 teodor 230 GIC 6159 : else if (ISALLTRUE(b))
6060 teodor 231 UIC 0 : *result = false;
6031 bruce 232 ECB : else
6031 bruce 233 EUB : {
3940 peter_e 234 ECB : int32 i;
6031 bruce 235 GBC 6159 : BITVECP sa = GETSIGN(a),
6031 bruce 236 CBC 6159 : sb = GETSIGN(b);
6031 bruce 237 EUB :
6060 teodor 238 GIC 6159 : *result = true;
1105 akorotkov 239 4565619 : LOOPBYTE(siglen)
240 : {
5623 bruce 241 CBC 4564286 : if (sa[i] != sb[i])
5623 bruce 242 ECB : {
5623 bruce 243 GIC 4826 : *result = false;
5623 bruce 244 CBC 4826 : break;
5623 bruce 245 ECB : }
246 : }
6060 teodor 247 : }
6060 teodor 248 GIC 6159 : PG_RETURN_POINTER(result);
6060 teodor 249 ECB : }
250 :
251 : static int32
1105 akorotkov 252 UIC 0 : sizebitvec(BITVECP sign, int siglen)
253 : {
3940 peter_e 254 LBC 0 : int32 size = 0,
255 : i;
256 :
1105 akorotkov 257 UIC 0 : LOOPBYTE(siglen)
5623 bruce 258 EUB : {
5623 bruce 259 UIC 0 : size += SUMBIT(sign);
5623 bruce 260 UBC 0 : sign = (BITVECP) (((char *) sign) + 1);
261 : }
6060 teodor 262 UIC 0 : return size;
6060 teodor 263 EUB : }
264 :
265 : static int
1105 akorotkov 266 GBC 132428 : hemdistsign(BITVECP a, BITVECP b, int siglen)
267 : {
6031 bruce 268 EUB : int i,
6031 bruce 269 GIC 132428 : dist = 0;
270 :
1105 akorotkov 271 383229964 : LOOPBIT(siglen)
5623 bruce 272 ECB : {
5623 bruce 273 GIC 383097536 : if (GETBIT(a, i) != GETBIT(b, i))
6060 teodor 274 3347577 : dist++;
5623 bruce 275 ECB : }
6060 teodor 276 GIC 132428 : return dist;
6060 teodor 277 ECB : }
278 :
279 : static int
1105 akorotkov 280 CBC 132428 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
281 : {
6031 bruce 282 132428 : if (ISALLTRUE(a))
283 : {
6060 teodor 284 UIC 0 : if (ISALLTRUE(b))
285 0 : return 0;
6060 teodor 286 ECB : else
1105 akorotkov 287 UIC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
6031 bruce 288 ECB : }
6031 bruce 289 GIC 132428 : else if (ISALLTRUE(b))
1105 akorotkov 290 UBC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
6060 teodor 291 EUB :
1105 akorotkov 292 GIC 132428 : return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
6060 teodor 293 EUB : }
294 :
3940 peter_e 295 ECB : static int32
1105 akorotkov 296 GBC 12318 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
297 : {
3940 peter_e 298 ECB : int32 i;
6031 bruce 299 GIC 12318 : BITVECP sadd = GETSIGN(add);
300 :
6060 teodor 301 12318 : if (ISALLTRUE(add))
6060 teodor 302 LBC 0 : return 1;
1105 akorotkov 303 GIC 21743198 : LOOPBYTE(siglen)
5623 bruce 304 21730880 : sbase[i] |= sadd[i];
6060 teodor 305 CBC 12318 : return 0;
306 : }
6060 teodor 307 ECB :
6060 teodor 308 EUB : Datum
6031 bruce 309 CBC 6159 : ghstore_union(PG_FUNCTION_ARGS)
6031 bruce 310 ECB : {
6031 bruce 311 CBC 6159 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
3940 peter_e 312 GIC 6159 : int32 len = entryvec->n;
313 :
6031 bruce 314 6159 : int *size = (int *) PG_GETARG_POINTER(1);
1105 akorotkov 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 :
6031 bruce 320 18477 : for (i = 0; i < len; i++)
6031 bruce 321 ECB : {
1105 akorotkov 322 GIC 12318 : if (unionkey(base, GETENTRY(entryvec, i), siglen))
6031 bruce 323 ECB : {
1105 akorotkov 324 LBC 0 : result->flag |= ALLISTRUE;
1105 akorotkov 325 UIC 0 : SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
6060 teodor 326 LBC 0 : break;
327 : }
6060 teodor 328 ECB : }
329 :
1105 akorotkov 330 GBC 6159 : *size = VARSIZE(result);
6060 teodor 331 EUB :
6060 teodor 332 GBC 6159 : PG_RETURN_POINTER(result);
333 : }
334 :
335 : Datum
6031 bruce 336 CBC 16073 : ghstore_penalty(PG_FUNCTION_ARGS)
337 : {
6060 teodor 338 16073 : GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
6060 teodor 339 GIC 16073 : GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
6031 bruce 340 16073 : float *penalty = (float *) PG_GETARG_POINTER(2);
1105 akorotkov 341 16073 : int siglen = GET_SIGLEN();
6060 teodor 342 CBC 16073 : GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
6060 teodor 343 GIC 16073 : GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
6060 teodor 344 ECB :
1105 akorotkov 345 CBC 16073 : *penalty = hemdist(origval, newval, siglen);
6060 teodor 346 16073 : PG_RETURN_POINTER(penalty);
6060 teodor 347 ECB : }
348 :
349 :
350 : typedef struct
6031 bruce 351 : {
6060 teodor 352 : OffsetNumber pos;
353 : int32 cost;
354 : } SPLITCOST;
355 :
356 : static int
6031 bruce 357 GIC 5946 : comparecost(const void *a, const void *b)
358 : {
4228 peter_e 359 5946 : return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
360 : }
361 :
362 :
6060 teodor 363 ECB : Datum
6031 bruce 364 GIC 657 : ghstore_picksplit(PG_FUNCTION_ARGS)
6031 bruce 365 ECB : {
6031 bruce 366 GIC 657 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
6060 teodor 367 657 : OffsetNumber maxoff = entryvec->n - 2;
368 :
369 657 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1105 akorotkov 370 CBC 657 : int siglen = GET_SIGLEN();
371 : OffsetNumber k,
6060 teodor 372 ECB : j;
6031 bruce 373 : GISTTYPE *datum_l,
374 : *datum_r;
375 : BITVECP union_l,
6060 teodor 376 : union_r;
377 : int32 size_alpha,
378 : size_beta;
379 : int32 size_waste,
6060 teodor 380 GIC 657 : waste = -1;
381 : int32 nbytes;
382 657 : OffsetNumber seed_1 = 0,
383 657 : seed_2 = 0;
384 : OffsetNumber *left,
385 : *right;
6031 bruce 386 ECB : BITVECP ptr;
387 : int i;
6060 teodor 388 : SPLITCOST *costvector;
6031 bruce 389 : GISTTYPE *_k,
390 : *_j;
391 :
6060 teodor 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 :
6031 bruce 396 2971 : for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
397 : {
6060 teodor 398 CBC 2314 : _k = GETENTRY(entryvec, k);
6031 bruce 399 106785 : for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
6031 bruce 400 ECB : {
1105 akorotkov 401 GIC 104471 : size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
6031 bruce 402 CBC 104471 : if (size_waste > waste)
403 : {
6060 teodor 404 1089 : waste = size_waste;
405 1089 : seed_1 = k;
6060 teodor 406 GIC 1089 : seed_2 = j;
6060 teodor 407 ECB : }
408 : }
409 : }
410 :
6060 teodor 411 CBC 657 : left = v->spl_left;
412 657 : v->spl_nleft = 0;
6060 teodor 413 GIC 657 : right = v->spl_right;
414 657 : v->spl_nright = 0;
415 :
416 657 : if (seed_1 == 0 || seed_2 == 0)
6060 teodor 417 ECB : {
6060 teodor 418 LBC 0 : seed_1 = 1;
419 0 : seed_2 = 2;
6060 teodor 420 ECB : }
421 :
422 : /* form initial .. */
1105 akorotkov 423 GIC 657 : datum_l = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
1105 akorotkov 424 GBC 657 : GETSIGN(GETENTRY(entryvec, seed_1)));
425 657 : datum_r = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
1105 akorotkov 426 GIC 657 : GETSIGN(GETENTRY(entryvec, seed_2)));
427 :
6060 teodor 428 657 : maxoff = OffsetNumberNext(maxoff);
6060 teodor 429 ECB : /* sort before ... */
6060 teodor 430 CBC 657 : costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
431 4285 : for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
6060 teodor 432 ECB : {
6060 teodor 433 GIC 3628 : costvector[j - 1].pos = j;
6060 teodor 434 CBC 3628 : _j = GETENTRY(entryvec, j);
1105 akorotkov 435 GIC 3628 : size_alpha = hemdist(datum_l, _j, siglen);
1105 akorotkov 436 CBC 3628 : size_beta = hemdist(datum_r, _j, siglen);
6060 teodor 437 3628 : costvector[j - 1].cost = abs(size_alpha - size_beta);
438 : }
61 peter 439 GNC 657 : qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
6060 teodor 440 ECB :
6031 bruce 441 CBC 657 : union_l = GETSIGN(datum_l);
442 657 : union_r = GETSIGN(datum_r);
6060 teodor 443 ECB :
6031 bruce 444 GIC 4285 : for (k = 0; k < maxoff; k++)
6031 bruce 445 ECB : {
6060 teodor 446 GIC 3628 : j = costvector[k].pos;
6031 bruce 447 CBC 3628 : if (j == seed_1)
6031 bruce 448 ECB : {
6060 teodor 449 GIC 657 : *left++ = j;
6060 teodor 450 CBC 657 : v->spl_nleft++;
6060 teodor 451 GIC 657 : continue;
6031 bruce 452 ECB : }
6031 bruce 453 CBC 2971 : else if (j == seed_2)
454 : {
6060 teodor 455 657 : *right++ = j;
456 657 : v->spl_nright++;
457 657 : continue;
458 : }
459 2314 : _j = GETENTRY(entryvec, j);
1105 akorotkov 460 GIC 2314 : size_alpha = hemdist(datum_l, _j, siglen);
1105 akorotkov 461 CBC 2314 : size_beta = hemdist(datum_r, _j, siglen);
6060 teodor 462 ECB :
6031 bruce 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))
6031 bruce 466 ECB : {
6060 teodor 467 LBC 0 : if (!ISALLTRUE(datum_l))
61 peter 468 UNC 0 : memset(union_l, 0xff, siglen);
6031 bruce 469 ECB : }
470 : else
471 : {
6031 bruce 472 GIC 1126 : ptr = GETSIGN(_j);
1105 akorotkov 473 GBC 1278158 : LOOPBYTE(siglen)
5623 bruce 474 1277032 : union_l[i] |= ptr[i];
475 : }
6060 teodor 476 GIC 1126 : *left++ = j;
477 1126 : v->spl_nleft++;
6031 bruce 478 ECB : }
479 : else
480 : {
6031 bruce 481 GIC 1188 : if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
6031 bruce 482 ECB : {
6060 teodor 483 LBC 0 : if (!ISALLTRUE(datum_r))
61 peter 484 UNC 0 : memset(union_r, 0xff, siglen);
485 : }
486 : else
6031 bruce 487 ECB : {
6031 bruce 488 GIC 1188 : ptr = GETSIGN(_j);
1105 akorotkov 489 GBC 1379612 : LOOPBYTE(siglen)
5623 bruce 490 1378424 : union_r[i] |= ptr[i];
491 : }
6060 teodor 492 GIC 1188 : *right++ = j;
493 1188 : v->spl_nright++;
6060 teodor 494 ECB : }
495 : }
496 :
6060 teodor 497 GIC 657 : *right = *left = FirstOffsetNumber;
6060 teodor 498 ECB :
6060 teodor 499 CBC 657 : v->spl_ldatum = PointerGetDatum(datum_l);
6060 teodor 500 GIC 657 : v->spl_rdatum = PointerGetDatum(datum_r);
501 :
502 657 : PG_RETURN_POINTER(v);
6060 teodor 503 ECB : }
504 :
505 :
6031 bruce 506 : Datum
6031 bruce 507 GIC 10488 : ghstore_consistent(PG_FUNCTION_ARGS)
6031 bruce 508 ECB : {
6031 bruce 509 GIC 10488 : GISTTYPE *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
5870 teodor 510 10488 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
511 :
512 : /* Oid subtype = PG_GETARG_OID(3); */
5473 tgl 513 CBC 10488 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
1105 akorotkov 514 GIC 10488 : int siglen = GET_SIGLEN();
6031 bruce 515 CBC 10488 : bool res = true;
6031 bruce 516 ECB : BITVECP sign;
517 :
518 : /* All cases served by this function are inexact */
5473 tgl 519 CBC 10488 : *recheck = true;
5473 tgl 520 ECB :
6031 bruce 521 CBC 10488 : if (ISALLTRUE(entry))
6060 teodor 522 UIC 0 : PG_RETURN_BOOL(true);
523 :
6031 bruce 524 GIC 10488 : sign = GETSIGN(entry);
5870 teodor 525 ECB :
4939 tgl 526 GIC 10488 : if (strategy == HStoreContainsStrategyNumber ||
4939 tgl 527 ECB : strategy == HStoreOldContainsStrategyNumber)
6031 bruce 528 GBC 4691 : {
2029 tgl 529 GIC 4691 : HStore *query = PG_GETARG_HSTORE_P(1);
5870 teodor 530 CBC 4691 : HEntry *qe = ARRPTR(query);
5870 teodor 531 GIC 4691 : char *qv = STRPTR(query);
4790 bruce 532 CBC 4691 : int count = HS_COUNT(query);
533 : int i;
6031 bruce 534 ECB :
4939 tgl 535 CBC 9589 : for (i = 0; res && i < count; ++i)
6031 bruce 536 ECB : {
2698 tgl 537 CBC 4898 : int crc = crc32_sz((char *) HSTORE_KEY(qe, qv, i),
538 4898 : HSTORE_KEYLEN(qe, i));
539 :
1105 akorotkov 540 GIC 4898 : if (GETBIT(sign, HASHVAL(crc, siglen)))
6031 bruce 541 ECB : {
2698 tgl 542 GIC 1961 : if (!HSTORE_VALISNULL(qe, i))
5870 teodor 543 ECB : {
2698 tgl 544 CBC 1170 : crc = crc32_sz((char *) HSTORE_VAL(qe, qv, i),
2698 tgl 545 GIC 1170 : HSTORE_VALLEN(qe, i));
1105 akorotkov 546 CBC 1170 : if (!GETBIT(sign, HASHVAL(crc, siglen)))
5870 teodor 547 GIC 583 : res = false;
5870 teodor 548 ECB : }
549 : }
550 : else
5870 teodor 551 CBC 2937 : res = false;
6031 bruce 552 ECB : }
6060 teodor 553 : }
5623 bruce 554 GIC 5797 : else if (strategy == HStoreExistsStrategyNumber)
555 : {
4939 tgl 556 1939 : text *query = PG_GETARG_TEXT_PP(1);
4939 tgl 557 CBC 1939 : int crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
558 :
1105 akorotkov 559 GIC 1939 : res = (GETBIT(sign, HASHVAL(crc, siglen))) ? true : false;
5870 teodor 560 ECB : }
4939 tgl 561 GIC 3858 : else if (strategy == HStoreExistsAllStrategyNumber)
4939 tgl 562 ECB : {
4790 bruce 563 CBC 1622 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
564 : Datum *key_datums;
4790 bruce 565 ECB : bool *key_nulls;
566 : int key_count;
567 : int i;
568 :
282 peter 569 GNC 1622 : deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
570 :
4939 tgl 571 GIC 3875 : for (i = 0; res && i < key_count; ++i)
572 : {
4790 bruce 573 ECB : int crc;
574 :
4939 tgl 575 CBC 2253 : if (key_nulls[i])
4939 tgl 576 UIC 0 : continue;
4939 tgl 577 GIC 2253 : crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
1105 akorotkov 578 2253 : if (!(GETBIT(sign, HASHVAL(crc, siglen))))
2062 peter_e 579 CBC 1297 : res = false;
4939 tgl 580 EUB : }
4939 tgl 581 ECB : }
4939 tgl 582 CBC 2236 : else if (strategy == HStoreExistsAnyStrategyNumber)
4939 tgl 583 ECB : {
4790 bruce 584 GIC 2236 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
585 : Datum *key_datums;
4790 bruce 586 ECB : bool *key_nulls;
587 : int key_count;
588 : int i;
589 :
282 peter 590 GNC 2236 : deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
591 :
2062 peter_e 592 CBC 2236 : res = false;
593 :
4939 tgl 594 5916 : for (i = 0; !res && i < key_count; ++i)
595 : {
4790 bruce 596 ECB : int crc;
597 :
4939 tgl 598 GIC 3680 : if (key_nulls[i])
4939 tgl 599 UIC 0 : continue;
4939 tgl 600 CBC 3680 : crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
1105 akorotkov 601 GBC 3680 : if (GETBIT(sign, HASHVAL(crc, siglen)))
2062 peter_e 602 CBC 1201 : res = true;
4939 tgl 603 ECB : }
604 : }
605 : else
5870 teodor 606 UIC 0 : elog(ERROR, "Unsupported strategy number: %d", strategy);
607 :
6060 teodor 608 GBC 10488 : PG_RETURN_BOOL(res);
609 : }
1105 akorotkov 610 ECB :
611 : Datum
1105 akorotkov 612 GIC 9 : ghstore_options(PG_FUNCTION_ARGS)
613 : {
1105 akorotkov 614 CBC 9 : local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
615 :
616 9 : init_local_reloptions(relopts, sizeof(GistHstoreOptions));
1105 akorotkov 617 GIC 9 : add_local_int_reloption(relopts, "siglen",
1105 akorotkov 618 ECB : "signature length in bytes",
619 : SIGLEN_DEFAULT, 1, SIGLEN_MAX,
620 : offsetof(GistHstoreOptions, siglen));
621 :
1105 akorotkov 622 GIC 9 : PG_RETURN_VOID();
623 : }
|