Age Owner TLA Line data Source code
1 : /*
2 : * contrib/ltree/_ltree_gist.c
3 : *
4 : *
5 : * GiST support for ltree[]
6 : * Teodor Sigaev <teodor@stack.net>
7 : */
8 : #include "postgres.h"
9 :
10 : #include <math.h>
11 :
12 : #include "access/gist.h"
13 : #include "access/reloptions.h"
14 : #include "access/stratnum.h"
15 : #include "crc32.h"
16 : #include "ltree.h"
17 : #include "port/pg_bitutils.h"
18 : #include "utils/array.h"
19 :
7522 bruce 20 GIC 3 : PG_FUNCTION_INFO_V1(_ltree_compress);
21 3 : PG_FUNCTION_INFO_V1(_ltree_same);
22 3 : PG_FUNCTION_INFO_V1(_ltree_union);
7522 bruce 23 CBC 3 : PG_FUNCTION_INFO_V1(_ltree_penalty);
24 3 : PG_FUNCTION_INFO_V1(_ltree_picksplit);
25 3 : PG_FUNCTION_INFO_V1(_ltree_consistent);
1105 akorotkov 26 3 : PG_FUNCTION_INFO_V1(_ltree_gist_options);
7558 bruce 27 ECB :
6949 teodor 28 : #define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
7558 bruce 29 : #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
30 :
31 : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
32 :
33 :
34 : static void
1105 akorotkov 35 GIC 7058 : hashing(BITVECP sign, ltree *t, int siglen)
36 : {
7522 bruce 37 7058 : int tlen = t->numlevel;
7558 bruce 38 CBC 7058 : ltree_level *cur = LTREE_FIRST(t);
39 : int hash;
7558 bruce 40 ECB :
7522 bruce 41 CBC 53466 : while (tlen > 0)
42 : {
7522 bruce 43 GIC 46408 : hash = ltree_crc32_sz(cur->name, cur->len);
1105 akorotkov 44 CBC 46408 : AHASH(sign, hash, siglen);
7558 bruce 45 GIC 46408 : cur = LEVEL_NEXT(cur);
7558 bruce 46 CBC 46408 : tlen--;
7558 bruce 47 ECB : }
7558 bruce 48 CBC 7058 : }
7558 bruce 49 ECB :
50 : Datum
7522 bruce 51 CBC 5939 : _ltree_compress(PG_FUNCTION_ARGS)
52 : {
7522 bruce 53 GIC 5939 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
7558 bruce 54 CBC 5939 : GISTENTRY *retval = entry;
1105 akorotkov 55 GIC 5939 : int siglen = LTREE_GET_ASIGLEN();
7558 bruce 56 ECB :
7522 bruce 57 CBC 5939 : if (entry->leafkey)
7522 bruce 58 ECB : { /* ltree */
59 : ltree_gist *key;
7522 bruce 60 CBC 2000 : ArrayType *val = DatumGetArrayTypeP(entry->key);
7522 bruce 61 GIC 2000 : int num = ArrayGetNItems(ARR_NDIM(val), ARR_DIMS(val));
62 2000 : ltree *item = (ltree *) ARR_DATA_PTR(val);
7558 bruce 63 ECB :
4792 tgl 64 CBC 2000 : if (ARR_NDIM(val) > 1)
7199 tgl 65 LBC 0 : ereport(ERROR,
66 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
6797 bruce 67 ECB : errmsg("array must be one-dimensional")));
4473 tgl 68 GBC 2000 : if (array_contains_nulls(val))
6350 tgl 69 UIC 0 : ereport(ERROR,
70 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
6350 tgl 71 ECB : errmsg("array must not contain nulls")));
7558 bruce 72 EUB :
1105 akorotkov 73 GIC 2000 : key = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
74 :
7522 bruce 75 9058 : while (num > 0)
7522 bruce 76 ECB : {
1105 akorotkov 77 GIC 7058 : hashing(LTG_SIGN(key), item, siglen);
7558 bruce 78 CBC 7058 : num--;
7558 bruce 79 GIC 7058 : item = NEXTVAL(item);
7558 bruce 80 ECB : }
81 :
7522 bruce 82 CBC 2000 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
7558 bruce 83 GIC 2000 : gistentryinit(*retval, PointerGetDatum(key),
84 : entry->rel, entry->page,
2062 peter_e 85 ECB : entry->offset, false);
7522 bruce 86 : }
6797 bruce 87 GIC 3939 : else if (!LTG_ISALLTRUE(entry->key))
88 : {
89 : int32 i;
7522 bruce 90 ECB : ltree_gist *key;
7522 bruce 91 GIC 3939 : BITVECP sign = LTG_SIGN(DatumGetPointer(entry->key));
92 :
1105 akorotkov 93 3939 : ALOOPBYTE(siglen)
5623 bruce 94 ECB : {
5623 bruce 95 GIC 3939 : if ((sign[i] & 0xff) != 0xff)
5623 bruce 96 CBC 3939 : PG_RETURN_POINTER(retval);
97 : }
7558 bruce 98 ECB :
1105 akorotkov 99 LBC 0 : key = ltree_gist_alloc(true, sign, siglen, NULL, NULL);
7522 bruce 100 UIC 0 : retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
7558 101 0 : gistentryinit(*retval, PointerGetDatum(key),
7522 bruce 102 EUB : entry->rel, entry->page,
2062 peter_e 103 : entry->offset, false);
7558 bruce 104 : }
7558 bruce 105 GIC 2000 : PG_RETURN_POINTER(retval);
106 : }
107 :
7522 bruce 108 ECB : Datum
7522 bruce 109 GIC 8024 : _ltree_same(PG_FUNCTION_ARGS)
110 : {
111 8024 : ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
7522 bruce 112 CBC 8024 : ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
7522 bruce 113 GIC 8024 : bool *result = (bool *) PG_GETARG_POINTER(2);
1105 akorotkov 114 CBC 8024 : int siglen = LTREE_GET_ASIGLEN();
7558 bruce 115 ECB :
7522 bruce 116 CBC 8024 : if (LTG_ISALLTRUE(a) && LTG_ISALLTRUE(b))
7558 bruce 117 LBC 0 : *result = true;
7522 bruce 118 GIC 8024 : else if (LTG_ISALLTRUE(a))
7558 bruce 119 LBC 0 : *result = false;
7522 bruce 120 GBC 8024 : else if (LTG_ISALLTRUE(b))
7558 bruce 121 LBC 0 : *result = false;
7522 bruce 122 EUB : else
7522 bruce 123 ECB : {
3940 peter_e 124 EUB : int32 i;
7522 bruce 125 GIC 8024 : BITVECP sa = LTG_SIGN(a),
126 8024 : sb = LTG_SIGN(b);
127 :
7558 bruce 128 CBC 8024 : *result = true;
1105 akorotkov 129 11642858 : ALOOPBYTE(siglen)
130 : {
5623 bruce 131 11636903 : if (sa[i] != sb[i])
5623 bruce 132 ECB : {
5623 bruce 133 GIC 2069 : *result = false;
5623 bruce 134 CBC 2069 : break;
135 : }
7522 bruce 136 ECB : }
137 : }
7522 bruce 138 GIC 8024 : PG_RETURN_POINTER(result);
139 : }
140 :
3940 peter_e 141 ECB : static int32
1105 akorotkov 142 GIC 16048 : unionkey(BITVECP sbase, ltree_gist *add, int siglen)
143 : {
144 : int32 i;
7522 bruce 145 CBC 16048 : BITVECP sadd = LTG_SIGN(add);
146 :
7522 bruce 147 GIC 16048 : if (LTG_ISALLTRUE(add))
7558 bruce 148 LBC 0 : return 1;
149 :
1105 akorotkov 150 CBC 29068072 : ALOOPBYTE(siglen)
5623 bruce 151 GBC 29052024 : sbase[i] |= sadd[i];
7558 bruce 152 GIC 16048 : return 0;
7558 bruce 153 ECB : }
154 :
7522 155 : Datum
7522 bruce 156 GIC 8024 : _ltree_union(PG_FUNCTION_ARGS)
157 : {
6797 158 8024 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
7522 bruce 159 CBC 8024 : int *size = (int *) PG_GETARG_POINTER(1);
1105 akorotkov 160 GIC 8024 : int siglen = LTREE_GET_ASIGLEN();
1105 akorotkov 161 ECB : int32 i;
1105 akorotkov 162 CBC 8024 : ltree_gist *result = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
163 8024 : BITVECP base = LTG_SIGN(result);
164 :
6949 teodor 165 24072 : for (i = 0; i < entryvec->n; i++)
7522 bruce 166 ECB : {
1105 akorotkov 167 GIC 16048 : if (unionkey(base, GETENTRY(entryvec, i), siglen))
7522 bruce 168 ECB : {
1105 akorotkov 169 UIC 0 : result->flag |= LTG_ALLTRUE;
1105 akorotkov 170 LBC 0 : SET_VARSIZE(result, LTG_HDRSIZE);
7558 bruce 171 UIC 0 : break;
7558 bruce 172 EUB : }
173 : }
174 :
1105 akorotkov 175 GIC 8024 : *size = VARSIZE(result);
176 :
7522 bruce 177 8024 : PG_RETURN_POINTER(result);
7558 bruce 178 ECB : }
179 :
3940 peter_e 180 : static int32
1105 akorotkov 181 UIC 0 : sizebitvec(BITVECP sign, int siglen)
182 : {
183 0 : return pg_popcount((const char *) sign, siglen);
7558 bruce 184 EUB : }
185 :
6797 186 : static int
1105 akorotkov 187 GIC 115743 : hemdistsign(BITVECP a, BITVECP b, int siglen)
188 : {
189 : int i,
6288 tgl 190 ECB : diff,
6797 bruce 191 GIC 115743 : dist = 0;
192 :
1105 akorotkov 193 60639751 : ALOOPBYTE(siglen)
5623 bruce 194 ECB : {
5623 bruce 195 GIC 60524008 : diff = (unsigned char) (a[i] ^ b[i]);
1514 tgl 196 ECB : /* Using the popcount functions here isn't likely to win */
1514 tgl 197 GIC 60524008 : dist += pg_number_of_ones[diff];
5623 bruce 198 ECB : }
7242 bruce 199 GIC 115743 : return dist;
7242 bruce 200 ECB : }
201 :
202 : static int
1105 akorotkov 203 GIC 115743 : hemdist(ltree_gist *a, ltree_gist *b, int siglen)
204 : {
6797 bruce 205 115743 : if (LTG_ISALLTRUE(a))
6797 bruce 206 ECB : {
6797 bruce 207 UIC 0 : if (LTG_ISALLTRUE(b))
6797 bruce 208 LBC 0 : return 0;
209 : else
1105 akorotkov 210 UBC 0 : return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(b), siglen);
6797 bruce 211 EUB : }
6797 bruce 212 GIC 115743 : else if (LTG_ISALLTRUE(b))
1105 akorotkov 213 UBC 0 : return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(a), siglen);
214 :
1105 akorotkov 215 CBC 115743 : return hemdistsign(LTG_SIGN(a), LTG_SIGN(b), siglen);
7242 bruce 216 EUB : }
217 :
7242 bruce 218 ECB :
219 : Datum
7522 bruce 220 GIC 19518 : _ltree_penalty(PG_FUNCTION_ARGS)
221 : {
222 19518 : ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
7522 bruce 223 CBC 19518 : ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
7522 bruce 224 GIC 19518 : float *penalty = (float *) PG_GETARG_POINTER(2);
1105 akorotkov 225 CBC 19518 : int siglen = LTREE_GET_ASIGLEN();
7558 bruce 226 ECB :
1105 akorotkov 227 CBC 19518 : *penalty = hemdist(origval, newval, siglen);
7522 bruce 228 19518 : PG_RETURN_POINTER(penalty);
229 : }
7558 bruce 230 ECB :
7522 231 : typedef struct
232 : {
233 : OffsetNumber pos;
234 : int32 cost;
235 : } SPLITCOST;
236 :
237 : static int
7522 bruce 238 GIC 7911 : comparecost(const void *a, const void *b)
239 : {
4228 peter_e 240 7911 : return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
7558 bruce 241 ECB : }
242 :
7522 243 : Datum
7522 bruce 244 GIC 935 : _ltree_picksplit(PG_FUNCTION_ARGS)
245 : {
6797 246 935 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
7522 bruce 247 CBC 935 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1105 akorotkov 248 GIC 935 : int siglen = LTREE_GET_ASIGLEN();
7522 bruce 249 ECB : OffsetNumber k,
250 : j;
251 : ltree_gist *datum_l,
252 : *datum_r;
253 : BITVECP union_l,
254 : union_r;
255 : int32 size_alpha,
256 : size_beta;
257 : int32 size_waste,
7242 bruce 258 GIC 935 : waste = -1;
259 : int32 nbytes;
7522 260 935 : OffsetNumber seed_1 = 0,
7522 bruce 261 CBC 935 : seed_2 = 0;
262 : OffsetNumber *left,
7522 bruce 263 ECB : *right;
7558 264 : OffsetNumber maxoff;
265 : BITVECP ptr;
266 : int i;
267 : SPLITCOST *costvector;
268 : ltree_gist *_k,
269 : *_j;
270 :
6949 teodor 271 GIC 935 : maxoff = entryvec->n - 2;
7558 bruce 272 935 : nbytes = (maxoff + 2) * sizeof(OffsetNumber);
273 935 : v->spl_left = (OffsetNumber *) palloc(nbytes);
7558 bruce 274 CBC 935 : v->spl_right = (OffsetNumber *) palloc(nbytes);
7558 bruce 275 ECB :
6797 bruce 276 CBC 3901 : for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
6797 bruce 277 ECB : {
7522 bruce 278 GIC 2966 : _k = GETENTRY(entryvec, k);
6797 bruce 279 CBC 83587 : for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
280 : {
1105 akorotkov 281 80621 : size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
6797 bruce 282 80621 : if (size_waste > waste)
283 : {
7558 284 1744 : waste = size_waste;
285 1744 : seed_1 = k;
7558 bruce 286 GIC 1744 : seed_2 = j;
7558 bruce 287 ECB : }
288 : }
289 : }
290 :
7558 bruce 291 GIC 935 : left = v->spl_left;
292 935 : v->spl_nleft = 0;
293 935 : right = v->spl_right;
7558 bruce 294 CBC 935 : v->spl_nright = 0;
7558 bruce 295 ECB :
7522 bruce 296 CBC 935 : if (seed_1 == 0 || seed_2 == 0)
7522 bruce 297 ECB : {
7558 bruce 298 UIC 0 : seed_1 = 1;
7558 bruce 299 LBC 0 : seed_2 = 2;
300 : }
7558 bruce 301 EUB :
302 : /* form initial .. */
1105 akorotkov 303 GIC 935 : datum_l = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_1)),
304 935 : LTG_SIGN(GETENTRY(entryvec, seed_1)),
305 : siglen, NULL, NULL);
1105 akorotkov 306 ECB :
1105 akorotkov 307 CBC 935 : datum_r = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_2)),
1105 akorotkov 308 GIC 935 : LTG_SIGN(GETENTRY(entryvec, seed_2)),
309 : siglen, NULL, NULL);
7558 bruce 310 ECB :
7558 bruce 311 CBC 935 : maxoff = OffsetNumberNext(maxoff);
312 : /* sort before ... */
7522 bruce 313 GIC 935 : costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
7522 bruce 314 CBC 5771 : for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
315 : {
316 4836 : costvector[j - 1].pos = j;
317 4836 : _j = GETENTRY(entryvec, j);
1105 akorotkov 318 GIC 4836 : size_alpha = hemdist(datum_l, _j, siglen);
1105 akorotkov 319 CBC 4836 : size_beta = hemdist(datum_r, _j, siglen);
184 peter 320 GNC 4836 : costvector[j - 1].cost = abs(size_alpha - size_beta);
7558 bruce 321 ECB : }
61 peter 322 GNC 935 : qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
7558 bruce 323 ECB :
6797 bruce 324 GIC 935 : union_l = LTG_SIGN(datum_l);
6797 bruce 325 CBC 935 : union_r = LTG_SIGN(datum_r);
326 :
7522 327 5771 : for (k = 0; k < maxoff; k++)
7522 bruce 328 ECB : {
7558 bruce 329 GIC 4836 : j = costvector[k].pos;
7522 bruce 330 CBC 4836 : if (j == seed_1)
331 : {
7558 332 935 : *left++ = j;
333 935 : v->spl_nleft++;
7558 bruce 334 GIC 935 : continue;
7522 bruce 335 ECB : }
7522 bruce 336 CBC 3901 : else if (j == seed_2)
7522 bruce 337 ECB : {
7558 bruce 338 GIC 935 : *right++ = j;
7558 bruce 339 CBC 935 : v->spl_nright++;
7558 bruce 340 GIC 935 : continue;
7558 bruce 341 ECB : }
7242 bruce 342 CBC 2966 : _j = GETENTRY(entryvec, j);
1105 akorotkov 343 2966 : size_alpha = hemdist(datum_l, _j, siglen);
1105 akorotkov 344 GIC 2966 : size_beta = hemdist(datum_r, _j, siglen);
7558 bruce 345 ECB :
6797 bruce 346 CBC 2966 : if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
7522 bruce 347 ECB : {
6797 bruce 348 GIC 1410 : if (LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j))
6797 bruce 349 ECB : {
7242 bruce 350 UIC 0 : if (!LTG_ISALLTRUE(datum_l))
61 peter 351 UNC 0 : memset(union_l, 0xff, siglen);
352 : }
6797 bruce 353 EUB : else
354 : {
6797 bruce 355 GIC 1410 : ptr = LTG_SIGN(_j);
1105 akorotkov 356 1731502 : ALOOPBYTE(siglen)
5623 bruce 357 1730092 : union_l[i] |= ptr[i];
7558 bruce 358 ECB : }
7558 bruce 359 CBC 1410 : *left++ = j;
360 1410 : v->spl_nleft++;
361 : }
7522 bruce 362 ECB : else
363 : {
6797 bruce 364 GIC 1556 : if (LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j))
365 : {
7242 bruce 366 UIC 0 : if (!LTG_ISALLTRUE(datum_r))
61 peter 367 UNC 0 : memset(union_r, 0xff, siglen);
368 : }
6797 bruce 369 EUB : else
370 : {
6797 bruce 371 GIC 1556 : ptr = LTG_SIGN(_j);
1105 akorotkov 372 2055096 : ALOOPBYTE(siglen)
5623 bruce 373 2053540 : union_r[i] |= ptr[i];
7558 bruce 374 ECB : }
7558 bruce 375 CBC 1556 : *right++ = j;
376 1556 : v->spl_nright++;
377 : }
7558 bruce 378 ECB : }
379 :
7558 bruce 380 GIC 935 : *right = *left = FirstOffsetNumber;
381 :
382 935 : v->spl_ldatum = PointerGetDatum(datum_l);
7558 bruce 383 CBC 935 : v->spl_rdatum = PointerGetDatum(datum_r);
384 :
7522 385 935 : PG_RETURN_POINTER(v);
7558 bruce 386 ECB : }
387 :
388 : static bool
1105 akorotkov 389 GIC 2592 : gist_te(ltree_gist *key, ltree *query, int siglen)
390 : {
7522 bruce 391 2592 : ltree_level *curq = LTREE_FIRST(query);
7522 bruce 392 CBC 2592 : BITVECP sign = LTG_SIGN(key);
7522 bruce 393 GIC 2592 : int qlen = query->numlevel;
7558 bruce 394 ECB : unsigned int hv;
395 :
7522 bruce 396 CBC 2592 : if (LTG_ISALLTRUE(key))
7558 bruce 397 UIC 0 : return true;
398 :
7522 bruce 399 CBC 8739 : while (qlen > 0)
7522 bruce 400 EUB : {
7522 bruce 401 GIC 6690 : hv = ltree_crc32_sz(curq->name, curq->len);
1105 akorotkov 402 CBC 6690 : if (!GETBIT(sign, AHASHVAL(hv, siglen)))
7522 bruce 403 GIC 543 : return false;
7558 bruce 404 CBC 6147 : curq = LEVEL_NEXT(curq);
405 6147 : qlen--;
7558 bruce 406 ECB : }
407 :
7558 bruce 408 CBC 2049 : return true;
409 : }
410 :
1105 akorotkov 411 ECB : typedef struct LtreeSignature
412 : {
413 : BITVECP sign;
414 : int siglen;
415 : } LtreeSignature;
416 :
417 : static bool
1105 akorotkov 418 GIC 3827 : checkcondition_bit(void *cxt, ITEM *val)
419 : {
420 3827 : LtreeSignature *sig = cxt;
1105 akorotkov 421 ECB :
1105 akorotkov 422 GIC 3827 : return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(sig->sign, AHASHVAL(val->val, sig->siglen)) : true;
7558 bruce 423 ECB : }
424 :
425 : static bool
1105 akorotkov 426 GIC 2276 : gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
427 : {
428 : LtreeSignature sig;
1105 akorotkov 429 ECB :
7522 bruce 430 GIC 2276 : if (LTG_ISALLTRUE(key))
7558 bruce 431 UIC 0 : return true;
432 :
1105 akorotkov 433 CBC 2276 : sig.sign = LTG_SIGN(key);
1105 akorotkov 434 GBC 2276 : sig.siglen = siglen;
435 :
1165 alvherre 436 CBC 2276 : return ltree_execute(GETQUERY(query),
1105 akorotkov 437 ECB : &sig, false,
438 : checkcondition_bit);
7558 bruce 439 : }
440 :
441 : static bool
1105 akorotkov 442 GIC 15188 : gist_qe(ltree_gist *key, lquery *query, int siglen)
443 : {
7522 bruce 444 15188 : lquery_level *curq = LQUERY_FIRST(query);
7522 bruce 445 CBC 15188 : BITVECP sign = LTG_SIGN(key);
7522 bruce 446 GIC 15188 : int qlen = query->numlevel;
7522 bruce 447 ECB :
7522 bruce 448 CBC 15188 : if (LTG_ISALLTRUE(key))
7558 bruce 449 LBC 0 : return true;
450 :
7522 bruce 451 CBC 46144 : while (qlen > 0)
7522 bruce 452 EUB : {
7522 bruce 453 GIC 36873 : if (curq->numvar && LQL_CANLOOKSIGN(curq))
7522 bruce 454 ECB : {
7522 bruce 455 GIC 25759 : bool isexist = false;
7522 bruce 456 CBC 25759 : int vlen = curq->numvar;
7558 bruce 457 GIC 25759 : lquery_variant *curv = LQL_FIRST(curq);
7522 bruce 458 ECB :
7522 bruce 459 CBC 31676 : while (vlen > 0)
7522 bruce 460 ECB : {
1105 akorotkov 461 GIC 25759 : if (GETBIT(sign, AHASHVAL(curv->val, siglen)))
7522 bruce 462 ECB : {
7522 bruce 463 GIC 19842 : isexist = true;
7558 bruce 464 CBC 19842 : break;
465 : }
466 5917 : curv = LVAR_NEXT(curv);
467 5917 : vlen--;
468 : }
7522 469 25759 : if (!isexist)
7558 470 5917 : return false;
471 : }
7522 bruce 472 ECB :
7558 bruce 473 CBC 30956 : curq = LQL_NEXT(curq);
7558 bruce 474 GIC 30956 : qlen--;
475 : }
7558 bruce 476 ECB :
7558 bruce 477 CBC 9271 : return true;
478 : }
479 :
7354 bruce 480 ECB : static bool
1105 akorotkov 481 GIC 2429 : _arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
482 : {
6797 bruce 483 2429 : lquery *query = (lquery *) ARR_DATA_PTR(_query);
6797 bruce 484 CBC 2429 : int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
485 :
4792 tgl 486 2429 : if (ARR_NDIM(_query) > 1)
6797 bruce 487 LBC 0 : ereport(ERROR,
488 : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
7199 tgl 489 ECB : errmsg("array must be one-dimensional")));
4473 tgl 490 GBC 2429 : if (array_contains_nulls(_query))
6350 tgl 491 UIC 0 : ereport(ERROR,
492 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
6350 tgl 493 ECB : errmsg("array must not contain nulls")));
7354 bruce 494 EUB :
6797 bruce 495 GIC 4462 : while (num > 0)
496 : {
1105 akorotkov 497 3560 : if (gist_qe(key, query, siglen))
6797 bruce 498 CBC 1527 : return true;
6797 bruce 499 GIC 2033 : num--;
6797 bruce 500 CBC 2033 : query = (lquery *) NEXTVAL(query);
6797 bruce 501 ECB : }
6797 bruce 502 CBC 902 : return false;
7354 bruce 503 ECB : }
504 :
7522 505 : Datum
7522 bruce 506 GIC 18925 : _ltree_consistent(PG_FUNCTION_ARGS)
507 : {
508 18925 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
2029 tgl 509 CBC 18925 : void *query = (void *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
7558 bruce 510 GIC 18925 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
5050 bruce 511 ECB :
5473 tgl 512 : /* Oid subtype = PG_GETARG_OID(3); */
5473 tgl 513 CBC 18925 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
1105 akorotkov 514 GIC 18925 : int siglen = LTREE_GET_ASIGLEN();
5473 tgl 515 18925 : ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
7522 bruce 516 CBC 18925 : bool res = false;
7558 bruce 517 ECB :
5473 tgl 518 : /* All cases served by this function are inexact */
5473 tgl 519 CBC 18925 : *recheck = true;
520 :
7522 bruce 521 GIC 18925 : switch (strategy)
7522 bruce 522 ECB : {
7558 bruce 523 GIC 2592 : case 10:
7558 bruce 524 ECB : case 11:
1105 akorotkov 525 GIC 2592 : res = gist_te(key, (ltree *) query, siglen);
7558 bruce 526 CBC 2592 : break;
7558 bruce 527 GIC 11628 : case 12:
7558 bruce 528 ECB : case 13:
1105 akorotkov 529 CBC 11628 : res = gist_qe(key, (lquery *) query, siglen);
7522 bruce 530 11628 : break;
7558 bruce 531 GIC 2276 : case 14:
7558 bruce 532 ECB : case 15:
1105 akorotkov 533 CBC 2276 : res = gist_qtxt(key, (ltxtquery *) query, siglen);
7522 bruce 534 2276 : break;
7354 bruce 535 GIC 2429 : case 16:
7354 bruce 536 ECB : case 17:
1105 akorotkov 537 CBC 2429 : res = _arrq_cons(key, (ArrayType *) query, siglen);
7354 bruce 538 2429 : break;
7558 bruce 539 UIC 0 : default:
7199 tgl 540 ECB : /* internal error */
7199 tgl 541 LBC 0 : elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
7558 bruce 542 EUB : }
6031 bruce 543 GIC 18925 : PG_FREE_IF_COPY(query, 1);
7558 bruce 544 GBC 18925 : PG_RETURN_BOOL(res);
545 : }
1105 akorotkov 546 ECB :
547 : Datum
1105 akorotkov 548 GIC 9 : _ltree_gist_options(PG_FUNCTION_ARGS)
549 : {
550 9 : local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
1105 akorotkov 551 ECB :
1105 akorotkov 552 GIC 9 : init_local_reloptions(relopts, sizeof(LtreeGistOptions));
1105 akorotkov 553 CBC 9 : add_local_int_reloption(relopts, "siglen", "signature length",
554 : LTREE_ASIGLEN_DEFAULT, 1, LTREE_ASIGLEN_MAX,
1105 akorotkov 555 ECB : offsetof(LtreeGistOptions, siglen));
556 :
1105 akorotkov 557 GIC 9 : PG_RETURN_VOID();
558 : }
|