Age Owner TLA Line data Source code
1 : /*
2 : * contrib/intarray/_intbig_gist.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include <math.h>
7 :
8 : #include "_int.h"
9 : #include "access/gist.h"
10 : #include "access/reloptions.h"
11 : #include "access/stratnum.h"
12 : #include "port/pg_bitutils.h"
13 :
14 : #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
15 : /*
16 : ** _intbig methods
17 : */
7242 bruce 18 GIC 2 : PG_FUNCTION_INFO_V1(g_intbig_consistent);
19 2 : PG_FUNCTION_INFO_V1(g_intbig_compress);
7242 bruce 20 CBC 2 : PG_FUNCTION_INFO_V1(g_intbig_decompress);
21 2 : PG_FUNCTION_INFO_V1(g_intbig_penalty);
22 2 : PG_FUNCTION_INFO_V1(g_intbig_picksplit);
23 2 : PG_FUNCTION_INFO_V1(g_intbig_union);
24 2 : PG_FUNCTION_INFO_V1(g_intbig_same);
1105 akorotkov 25 2 : PG_FUNCTION_INFO_V1(g_intbig_options);
1105 akorotkov 26 ECB :
7242 bruce 27 CBC 1 : PG_FUNCTION_INFO_V1(_intbig_in);
7242 bruce 28 GIC 1 : PG_FUNCTION_INFO_V1(_intbig_out);
6797 bruce 29 ECB :
7242 30 : Datum
6797 bruce 31 UIC 0 : _intbig_in(PG_FUNCTION_ARGS)
32 : {
6797 bruce 33 UBC 0 : ereport(ERROR,
34 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
35 : errmsg("cannot accept a value of type %s", "intbig_gkey")));
36 :
37 : PG_RETURN_VOID(); /* keep compiler quiet */
38 : }
39 :
40 : Datum
6797 bruce 41 UIC 0 : _intbig_out(PG_FUNCTION_ARGS)
42 : {
43 0 : ereport(ERROR,
6797 bruce 44 EUB : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
45 : errmsg("cannot display a value of type %s", "intbig_gkey")));
46 :
47 : PG_RETURN_VOID(); /* keep compiler quiet */
48 : }
49 :
50 : static GISTTYPE *
1105 akorotkov 51 GIC 85579 : _intbig_alloc(bool allistrue, int siglen, BITVECP sign)
52 : {
53 85579 : int flag = allistrue ? ALLISTRUE : 0;
54 85579 : int size = CALCGTSIZE(flag, siglen);
1105 akorotkov 55 CBC 85579 : GISTTYPE *res = (GISTTYPE *) palloc(size);
56 :
57 85579 : SET_VARSIZE(res, size);
58 85579 : res->flag = flag;
1105 akorotkov 59 ECB :
1105 akorotkov 60 GIC 85579 : if (!allistrue)
1105 akorotkov 61 ECB : {
1105 akorotkov 62 CBC 85579 : if (sign)
1105 akorotkov 63 GIC 9082 : memcpy(GETSIGN(res), sign, siglen);
1105 akorotkov 64 ECB : else
1105 akorotkov 65 GIC 76497 : memset(GETSIGN(res), 0, siglen);
1105 akorotkov 66 ECB : }
67 :
1105 akorotkov 68 GIC 85579 : return res;
1105 akorotkov 69 ECB : }
70 :
71 :
7242 bruce 72 : /*********************************************************************
73 : ** intbig functions
74 : *********************************************************************/
75 : static bool
1105 akorotkov 76 GIC 7378 : _intbig_overlap(GISTTYPE *a, ArrayType *b, int siglen)
77 : {
6797 bruce 78 7378 : int num = ARRNELEMS(b);
3940 peter_e 79 7378 : int32 *ptr = ARRPTR(b);
7242 bruce 80 ECB :
6350 tgl 81 GIC 7378 : CHECKARRVALID(b);
6350 tgl 82 ECB :
6797 bruce 83 CBC 18844 : while (num--)
84 : {
1105 akorotkov 85 13544 : if (GETBIT(GETSIGN(a), HASHVAL(*ptr, siglen)))
7242 bruce 86 GIC 2078 : return true;
7242 bruce 87 CBC 11466 : ptr++;
88 : }
7242 bruce 89 ECB :
7242 bruce 90 CBC 5300 : return false;
7242 bruce 91 ECB : }
92 :
93 : static bool
1105 akorotkov 94 CBC 8063 : _intbig_contains(GISTTYPE *a, ArrayType *b, int siglen)
95 : {
6797 bruce 96 GIC 8063 : int num = ARRNELEMS(b);
3940 peter_e 97 8063 : int32 *ptr = ARRPTR(b);
7242 bruce 98 ECB :
6350 tgl 99 GIC 8063 : CHECKARRVALID(b);
6350 tgl 100 ECB :
6797 bruce 101 CBC 12411 : while (num--)
102 : {
1105 akorotkov 103 10969 : if (!GETBIT(GETSIGN(a), HASHVAL(*ptr, siglen)))
7242 bruce 104 GIC 6621 : return false;
7242 bruce 105 CBC 4348 : ptr++;
106 : }
7242 bruce 107 ECB :
7242 bruce 108 CBC 1442 : return true;
7242 bruce 109 ECB : }
110 :
111 : Datum
6797 bruce 112 CBC 62711 : g_intbig_same(PG_FUNCTION_ARGS)
113 : {
7242 bruce 114 GIC 62711 : GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
115 62711 : GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
6797 bruce 116 CBC 62711 : bool *result = (bool *) PG_GETARG_POINTER(2);
1105 akorotkov 117 GIC 62711 : int siglen = GET_SIGLEN();
7242 bruce 118 ECB :
7242 bruce 119 CBC 62711 : if (ISALLTRUE(a) && ISALLTRUE(b))
7242 bruce 120 LBC 0 : *result = true;
7242 bruce 121 CBC 62711 : else if (ISALLTRUE(a))
7242 bruce 122 UIC 0 : *result = false;
7242 bruce 123 CBC 62711 : else if (ISALLTRUE(b))
7242 bruce 124 UBC 0 : *result = false;
6797 bruce 125 ECB : else
6797 bruce 126 EUB : {
3940 peter_e 127 ECB : int32 i;
6797 bruce 128 GBC 62711 : BITVECP sa = GETSIGN(a),
6797 bruce 129 GIC 62711 : sb = GETSIGN(b);
130 :
7242 131 62711 : *result = true;
1105 akorotkov 132 CBC 46565798 : LOOPBYTE(siglen)
5623 bruce 133 ECB : {
5623 bruce 134 GIC 46537472 : if (sa[i] != sb[i])
5623 bruce 135 ECB : {
5623 bruce 136 CBC 34385 : *result = false;
5623 bruce 137 GIC 34385 : break;
5623 bruce 138 ECB : }
139 : }
7242 140 : }
7242 bruce 141 CBC 62711 : PG_RETURN_POINTER(result);
142 : }
143 :
144 : Datum
145 56991 : g_intbig_compress(PG_FUNCTION_ARGS)
146 : {
7242 bruce 147 GIC 56991 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1105 akorotkov 148 56991 : int siglen = GET_SIGLEN();
7242 bruce 149 ECB :
6797 bruce 150 GIC 56991 : if (entry->leafkey)
6797 bruce 151 ECB : {
7242 152 : GISTENTRY *retval;
4473 tgl 153 GIC 13512 : ArrayType *in = DatumGetArrayTypeP(entry->key);
3940 peter_e 154 ECB : int32 *ptr;
155 : int num;
1105 akorotkov 156 GIC 13512 : GISTTYPE *res = _intbig_alloc(false, siglen, NULL);
7242 bruce 157 ECB :
6350 tgl 158 GIC 13512 : CHECKARRVALID(in);
4473 159 13512 : if (ARRISEMPTY(in))
6350 tgl 160 ECB : {
6350 tgl 161 GIC 18 : ptr = NULL;
6350 tgl 162 CBC 18 : num = 0;
6350 tgl 163 ECB : }
164 : else
165 : {
6350 tgl 166 CBC 13494 : ptr = ARRPTR(in);
6350 tgl 167 GIC 13494 : num = ARRNELEMS(in);
168 : }
169 :
6797 bruce 170 CBC 67806 : while (num--)
6797 bruce 171 ECB : {
1105 akorotkov 172 GIC 54294 : HASH(GETSIGN(res), *ptr, siglen);
7242 bruce 173 54294 : ptr++;
7242 bruce 174 ECB : }
175 :
7242 bruce 176 CBC 13512 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
177 13512 : gistentryinit(*retval, PointerGetDatum(res),
178 : entry->rel, entry->page,
179 : entry->offset, false);
6797 bruce 180 ECB :
4473 tgl 181 CBC 13512 : if (in != DatumGetArrayTypeP(entry->key))
7242 bruce 182 GIC 13512 : pfree(in);
183 :
184 13512 : PG_RETURN_POINTER(retval);
6797 bruce 185 ECB : }
6797 bruce 186 CBC 43479 : else if (!ISALLTRUE(DatumGetPointer(entry->key)))
187 : {
7242 bruce 188 ECB : GISTENTRY *retval;
189 : int i;
6797 bruce 190 CBC 43479 : BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
191 : GISTTYPE *res;
192 :
1105 akorotkov 193 GIC 55206 : LOOPBYTE(siglen)
5623 bruce 194 ECB : {
5623 bruce 195 GIC 55206 : if ((sign[i] & 0xff) != 0xff)
196 43479 : PG_RETURN_POINTER(entry);
5623 bruce 197 ECB : }
198 :
1105 akorotkov 199 LBC 0 : res = _intbig_alloc(true, siglen, sign);
7242 bruce 200 0 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
7242 bruce 201 UIC 0 : gistentryinit(*retval, PointerGetDatum(res),
202 : entry->rel, entry->page,
2062 peter_e 203 EUB : entry->offset, false);
6797 bruce 204 :
7242 bruce 205 UBC 0 : PG_RETURN_POINTER(retval);
206 : }
207 :
7242 bruce 208 UIC 0 : PG_RETURN_POINTER(entry);
7242 bruce 209 EUB : }
210 :
211 :
3940 peter_e 212 : static int32
1105 akorotkov 213 UIC 0 : sizebitvec(BITVECP sign, int siglen)
214 : {
215 0 : return pg_popcount(sign, siglen);
216 : }
7242 bruce 217 EUB :
218 : static int
1105 akorotkov 219 GBC 498377 : hemdistsign(BITVECP a, BITVECP b, int siglen)
220 : {
221 : int i,
222 : diff,
6797 bruce 223 CBC 498377 : dist = 0;
224 :
1105 akorotkov 225 GIC 453515997 : LOOPBYTE(siglen)
226 : {
5623 bruce 227 CBC 453017620 : diff = (unsigned char) (a[i] ^ b[i]);
228 : /* Using the popcount functions here isn't likely to win */
1514 tgl 229 453017620 : dist += pg_number_of_ones[diff];
230 : }
6797 bruce 231 498377 : return dist;
232 : }
7242 bruce 233 ECB :
234 : static int
1105 akorotkov 235 CBC 498377 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
236 : {
6797 bruce 237 GIC 498377 : if (ISALLTRUE(a))
238 : {
6797 bruce 239 LBC 0 : if (ISALLTRUE(b))
6797 bruce 240 UIC 0 : return 0;
6797 bruce 241 ECB : else
1105 akorotkov 242 UIC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
6797 bruce 243 EUB : }
6797 bruce 244 GBC 498377 : else if (ISALLTRUE(b))
1105 akorotkov 245 UIC 0 : return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
6797 bruce 246 EUB :
1105 akorotkov 247 GIC 498377 : return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
7242 bruce 248 ECB : }
7242 bruce 249 EUB :
250 : Datum
7242 bruce 251 CBC 582318 : g_intbig_decompress(PG_FUNCTION_ARGS)
252 : {
7242 bruce 253 GIC 582318 : PG_RETURN_DATUM(PG_GETARG_DATUM(0));
254 : }
7242 bruce 255 ECB :
256 : static int32
1105 akorotkov 257 CBC 126324 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
258 : {
259 : int32 i;
6797 bruce 260 GIC 126324 : BITVECP sadd = GETSIGN(add);
7242 bruce 261 ECB :
7242 bruce 262 GIC 126324 : if (ISALLTRUE(add))
7242 bruce 263 UIC 0 : return 1;
1105 akorotkov 264 CBC 209269836 : LOOPBYTE(siglen)
5623 bruce 265 GIC 209143512 : sbase[i] |= sadd[i];
7242 bruce 266 CBC 126324 : return 0;
7242 bruce 267 EUB : }
7242 bruce 268 ECB :
269 : Datum
6797 bruce 270 CBC 62985 : g_intbig_union(PG_FUNCTION_ARGS)
271 : {
6797 bruce 272 GIC 62985 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
273 62985 : int *size = (int *) PG_GETARG_POINTER(1);
1105 akorotkov 274 CBC 62985 : int siglen = GET_SIGLEN();
275 : int32 i;
276 62985 : GISTTYPE *result = _intbig_alloc(false, siglen, NULL);
277 62985 : BITVECP base = GETSIGN(result);
7242 bruce 278 ECB :
6797 bruce 279 GIC 189309 : for (i = 0; i < entryvec->n; i++)
6797 bruce 280 ECB : {
1105 akorotkov 281 CBC 126324 : if (unionkey(base, GETENTRY(entryvec, i), siglen))
282 : {
1105 akorotkov 283 LBC 0 : result->flag |= ALLISTRUE;
1105 akorotkov 284 UIC 0 : SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
7242 bruce 285 LBC 0 : break;
286 : }
7242 bruce 287 EUB : }
288 :
1105 akorotkov 289 GBC 62985 : *size = VARSIZE(result);
290 :
7242 bruce 291 GIC 62985 : PG_RETURN_POINTER(result);
292 : }
7242 bruce 293 ECB :
294 : Datum
6797 bruce 295 CBC 298430 : g_intbig_penalty(PG_FUNCTION_ARGS)
296 : {
7242 bruce 297 GIC 298430 : GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
298 298430 : GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
6797 bruce 299 CBC 298430 : float *penalty = (float *) PG_GETARG_POINTER(2);
7242 bruce 300 GIC 298430 : GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
7242 bruce 301 CBC 298430 : GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
1105 akorotkov 302 298430 : int siglen = GET_SIGLEN();
7242 bruce 303 ECB :
1105 akorotkov 304 CBC 298430 : *penalty = hemdist(origval, newval, siglen);
7242 bruce 305 298430 : PG_RETURN_POINTER(penalty);
7242 bruce 306 ECB : }
307 :
308 :
6797 309 : typedef struct
310 : {
311 : OffsetNumber pos;
312 : int32 cost;
313 : } SPLITCOST;
314 :
315 : static int
6797 bruce 316 GIC 40299 : comparecost(const void *a, const void *b)
317 : {
4058 peter_e 318 40299 : return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
319 : }
7242 bruce 320 ECB :
321 :
322 : Datum
6797 bruce 323 GIC 4541 : g_intbig_picksplit(PG_FUNCTION_ARGS)
324 : {
325 4541 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
326 4541 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1105 akorotkov 327 CBC 4541 : int siglen = GET_SIGLEN();
328 : OffsetNumber k,
6797 bruce 329 ECB : j;
330 : GISTTYPE *datum_l,
331 : *datum_r;
332 : BITVECP union_l,
333 : union_r;
334 : int32 size_alpha,
335 : size_beta;
336 : int32 size_waste,
6797 bruce 337 GIC 4541 : waste = -1;
338 : int32 nbytes;
339 4541 : OffsetNumber seed_1 = 0,
340 4541 : seed_2 = 0;
6797 bruce 341 ECB : OffsetNumber *left,
342 : *right;
343 : OffsetNumber maxoff;
344 : BITVECP ptr;
345 : int i;
346 : SPLITCOST *costvector;
347 : GISTTYPE *_k,
348 : *_j;
349 :
6797 bruce 350 GIC 4541 : maxoff = entryvec->n - 2;
351 4541 : nbytes = (maxoff + 2) * sizeof(OffsetNumber);
352 4541 : v->spl_left = (OffsetNumber *) palloc(nbytes);
353 4541 : v->spl_right = (OffsetNumber *) palloc(nbytes);
6797 bruce 354 ECB :
6797 bruce 355 CBC 20943 : for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
6797 bruce 356 ECB : {
6797 bruce 357 CBC 16402 : _k = GETENTRY(entryvec, k);
6797 bruce 358 GIC 132577 : for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
6797 bruce 359 ECB : {
1105 akorotkov 360 GIC 116175 : size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
6797 bruce 361 CBC 116175 : if (size_waste > waste)
6797 bruce 362 ECB : {
6797 bruce 363 GIC 8826 : waste = size_waste;
6797 bruce 364 CBC 8826 : seed_1 = k;
365 8826 : seed_2 = j;
366 : }
6797 bruce 367 ECB : }
368 : }
369 :
6797 bruce 370 GIC 4541 : left = v->spl_left;
371 4541 : v->spl_nleft = 0;
372 4541 : right = v->spl_right;
373 4541 : v->spl_nright = 0;
6797 bruce 374 ECB :
6797 bruce 375 CBC 4541 : if (seed_1 == 0 || seed_2 == 0)
6797 bruce 376 ECB : {
6797 bruce 377 LBC 0 : seed_1 = 1;
6797 bruce 378 UIC 0 : seed_2 = 2;
6797 bruce 379 ECB : }
380 :
6797 bruce 381 EUB : /* form initial .. */
1105 akorotkov 382 GBC 4541 : datum_l = _intbig_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
1105 akorotkov 383 GIC 4541 : GETSIGN(GETENTRY(entryvec, seed_1)));
384 4541 : datum_r = _intbig_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
385 4541 : GETSIGN(GETENTRY(entryvec, seed_2)));
6797 bruce 386 ECB :
6797 bruce 387 CBC 4541 : maxoff = OffsetNumberNext(maxoff);
6797 bruce 388 ECB : /* sort before ... */
6797 bruce 389 CBC 4541 : costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
6797 bruce 390 GIC 30025 : for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
6797 bruce 391 ECB : {
6797 bruce 392 GIC 25484 : costvector[j - 1].pos = j;
6797 bruce 393 CBC 25484 : _j = GETENTRY(entryvec, j);
1105 akorotkov 394 25484 : size_alpha = hemdist(datum_l, _j, siglen);
1105 akorotkov 395 GIC 25484 : size_beta = hemdist(datum_r, _j, siglen);
184 peter 396 GNC 25484 : costvector[j - 1].cost = abs(size_alpha - size_beta);
6797 bruce 397 ECB : }
61 peter 398 GNC 4541 : qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
6797 bruce 399 ECB :
6797 bruce 400 CBC 4541 : union_l = GETSIGN(datum_l);
6797 bruce 401 GIC 4541 : union_r = GETSIGN(datum_r);
6797 bruce 402 ECB :
6797 bruce 403 GIC 30025 : for (k = 0; k < maxoff; k++)
6797 bruce 404 ECB : {
6797 bruce 405 CBC 25484 : j = costvector[k].pos;
6797 bruce 406 GIC 25484 : if (j == seed_1)
6797 bruce 407 ECB : {
6797 bruce 408 GIC 4541 : *left++ = j;
6797 bruce 409 CBC 4541 : v->spl_nleft++;
410 4541 : continue;
411 : }
412 20943 : else if (j == seed_2)
6797 bruce 413 ECB : {
6797 bruce 414 CBC 4541 : *right++ = j;
6797 bruce 415 GIC 4541 : v->spl_nright++;
6797 bruce 416 CBC 4541 : continue;
417 : }
418 16402 : _j = GETENTRY(entryvec, j);
1105 akorotkov 419 16402 : size_alpha = hemdist(datum_l, _j, siglen);
420 16402 : size_beta = hemdist(datum_r, _j, siglen);
421 :
6797 bruce 422 16402 : if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
6797 bruce 423 ECB : {
6797 bruce 424 CBC 8157 : if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
425 : {
6797 bruce 426 LBC 0 : if (!ISALLTRUE(datum_l))
61 peter 427 UNC 0 : memset(union_l, 0xff, siglen);
6797 bruce 428 ECB : }
429 : else
6797 bruce 430 EUB : {
6797 bruce 431 GBC 8157 : ptr = GETSIGN(_j);
1105 akorotkov 432 GIC 9314745 : LOOPBYTE(siglen)
5623 bruce 433 9306588 : union_l[i] |= ptr[i];
434 : }
6797 bruce 435 CBC 8157 : *left++ = j;
436 8157 : v->spl_nleft++;
6797 bruce 437 ECB : }
438 : else
439 : {
6797 bruce 440 CBC 8245 : if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
441 : {
6797 bruce 442 UIC 0 : if (!ISALLTRUE(datum_r))
61 peter 443 UNC 0 : memset(union_r, 0xff, siglen);
6797 bruce 444 ECB : }
445 : else
6797 bruce 446 EUB : {
6797 bruce 447 GBC 8245 : ptr = GETSIGN(_j);
1105 akorotkov 448 GIC 9801273 : LOOPBYTE(siglen)
5623 bruce 449 9793028 : union_r[i] |= ptr[i];
450 : }
6797 bruce 451 CBC 8245 : *right++ = j;
452 8245 : v->spl_nright++;
6797 bruce 453 ECB : }
454 : }
455 :
6797 bruce 456 CBC 4541 : *right = *left = FirstOffsetNumber;
6797 bruce 457 GIC 4541 : pfree(costvector);
458 :
459 4541 : v->spl_ldatum = PointerGetDatum(datum_l);
6797 bruce 460 CBC 4541 : v->spl_rdatum = PointerGetDatum(datum_r);
6797 bruce 461 ECB :
6797 bruce 462 GIC 4541 : PG_RETURN_POINTER(v);
7242 bruce 463 ECB : }
464 :
465 : Datum
7242 bruce 466 CBC 66447 : g_intbig_consistent(PG_FUNCTION_ARGS)
467 : {
7242 bruce 468 GIC 66447 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
4473 tgl 469 66447 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
7242 bruce 470 CBC 66447 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
471 :
5473 tgl 472 ECB : /* Oid subtype = PG_GETARG_OID(3); */
5473 tgl 473 CBC 66447 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
1105 akorotkov 474 66447 : int siglen = GET_SIGLEN();
475 : bool retval;
476 :
5473 tgl 477 ECB : /* All cases served by this function are inexact */
5473 tgl 478 CBC 66447 : *recheck = true;
479 :
6797 bruce 480 GIC 66447 : if (ISALLTRUE(DatumGetPointer(entry->key)))
7242 bruce 481 UIC 0 : PG_RETURN_BOOL(true);
6797 bruce 482 ECB :
6797 bruce 483 GIC 66447 : if (strategy == BooleanSearchStrategy)
6797 bruce 484 ECB : {
6031 bruce 485 GBC 50701 : retval = signconsistent((QUERYTYPE *) query,
6031 bruce 486 GIC 50701 : GETSIGN(DatumGetPointer(entry->key)),
1105 akorotkov 487 ECB : siglen,
488 : false);
6031 bruce 489 CBC 50701 : PG_FREE_IF_COPY(query, 1);
6215 teodor 490 50701 : PG_RETURN_BOOL(retval);
491 : }
492 :
6350 tgl 493 15746 : CHECKARRVALID(query);
7242 bruce 494 ECB :
7242 bruce 495 GIC 15746 : switch (strategy)
496 : {
7242 bruce 497 CBC 7378 : case RTOverlapStrategyNumber:
1105 akorotkov 498 GIC 7378 : retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key),
1105 akorotkov 499 ECB : query, siglen);
7242 bruce 500 GIC 7378 : break;
7242 bruce 501 CBC 881 : case RTSameStrategyNumber:
6797 502 881 : if (GIST_LEAF(entry))
503 : {
6797 bruce 504 ECB : int i,
6797 bruce 505 CBC 305 : num = ARRNELEMS(query);
3940 peter_e 506 305 : int32 *ptr = ARRPTR(query);
1105 akorotkov 507 GIC 305 : BITVECP dq = palloc0(siglen),
508 : de;
6797 bruce 509 ECB :
6797 bruce 510 CBC 1220 : while (num--)
6797 bruce 511 ECB : {
1105 akorotkov 512 GIC 915 : HASH(dq, *ptr, siglen);
7242 bruce 513 915 : ptr++;
7242 bruce 514 ECB : }
515 :
6797 bruce 516 CBC 305 : de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
517 305 : retval = true;
1105 akorotkov 518 GIC 3014 : LOOPBYTE(siglen)
519 : {
5623 bruce 520 CBC 3012 : if (de[i] != dq[i])
5623 bruce 521 ECB : {
5623 bruce 522 CBC 303 : retval = false;
5623 bruce 523 GIC 303 : break;
5623 bruce 524 ECB : }
525 : }
7242 526 :
1105 akorotkov 527 CBC 305 : pfree(dq);
528 : }
529 : else
1105 akorotkov 530 GIC 576 : retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key),
1105 akorotkov 531 ECB : query, siglen);
7242 bruce 532 GIC 881 : break;
533 7487 : case RTContainsStrategyNumber:
6055 tgl 534 ECB : case RTOldContainsStrategyNumber:
1105 akorotkov 535 GIC 7487 : retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key),
1105 akorotkov 536 ECB : query, siglen);
7242 bruce 537 CBC 7487 : break;
7242 bruce 538 UIC 0 : case RTContainedByStrategyNumber:
6055 tgl 539 ECB : case RTOldContainedByStrategyNumber:
540 :
974 541 : /*
974 tgl 542 EUB : * This code is unreachable as of intarray 1.4, because the <@
543 : * operator has been removed from the opclass. We keep it for now
544 : * to support older versions of the SQL definitions.
545 : */
6797 bruce 546 UIC 0 : if (GIST_LEAF(entry))
547 : {
548 : int i,
549 0 : num = ARRNELEMS(query);
3940 peter_e 550 UBC 0 : int32 *ptr = ARRPTR(query);
1105 akorotkov 551 UIC 0 : BITVECP dq = palloc0(siglen),
552 : de;
6797 bruce 553 EUB :
6797 bruce 554 UBC 0 : while (num--)
6797 bruce 555 EUB : {
1105 akorotkov 556 UIC 0 : HASH(dq, *ptr, siglen);
7242 bruce 557 0 : ptr++;
7242 bruce 558 EUB : }
559 :
6797 bruce 560 UBC 0 : de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
561 0 : retval = true;
1105 akorotkov 562 UIC 0 : LOOPBYTE(siglen)
563 : {
5623 bruce 564 UBC 0 : if (de[i] & ~dq[i])
5623 bruce 565 EUB : {
5623 bruce 566 UBC 0 : retval = false;
5623 bruce 567 UIC 0 : break;
5623 bruce 568 EUB : }
569 : }
6797 570 : }
571 : else
572 : {
573 : /*
574 : * Unfortunately, because empty arrays could be anywhere in
575 : * the index, we must search the whole tree.
576 : */
1342 tgl 577 UIC 0 : retval = true;
578 : }
7242 bruce 579 0 : break;
580 0 : default:
2062 peter_e 581 UBC 0 : retval = false;
582 : }
6031 bruce 583 GBC 15746 : PG_FREE_IF_COPY(query, 1);
7242 584 15746 : PG_RETURN_BOOL(retval);
7242 bruce 585 EUB : }
586 :
1105 akorotkov 587 ECB : Datum
1105 akorotkov 588 CBC 9 : g_intbig_options(PG_FUNCTION_ARGS)
589 : {
1105 akorotkov 590 GIC 9 : local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
591 :
1105 akorotkov 592 CBC 9 : init_local_reloptions(relopts, sizeof(GISTIntArrayBigOptions));
1105 akorotkov 593 GIC 9 : add_local_int_reloption(relopts, "siglen",
1105 akorotkov 594 ECB : "signature length in bytes",
595 : SIGLEN_DEFAULT, 1, SIGLEN_MAX,
596 : offsetof(GISTIntArrayBigOptions, siglen));
597 :
1105 akorotkov 598 GIC 9 : PG_RETURN_VOID();
599 : }
|