2 * contrib/intarray/_intbig_gist.c
6 #include "access/gist.h"
7 #include "access/stratnum.h"
8 #include "port/pg_bitutils.h"
12 #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
16 PG_FUNCTION_INFO_V1(g_intbig_consistent);
17 PG_FUNCTION_INFO_V1(g_intbig_compress);
18 PG_FUNCTION_INFO_V1(g_intbig_decompress);
19 PG_FUNCTION_INFO_V1(g_intbig_penalty);
20 PG_FUNCTION_INFO_V1(g_intbig_picksplit);
21 PG_FUNCTION_INFO_V1(g_intbig_union);
22 PG_FUNCTION_INFO_V1(g_intbig_same);
23 PG_FUNCTION_INFO_V1(_intbig_in);
24 PG_FUNCTION_INFO_V1(_intbig_out);
27 _intbig_in(PG_FUNCTION_ARGS)
30 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
31 errmsg("_intbig_in() not implemented")));
36 _intbig_out(PG_FUNCTION_ARGS)
39 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
40 errmsg("_intbig_out() not implemented")));
45 /*********************************************************************
47 *********************************************************************/
49 _intbig_overlap(GISTTYPE *a, ArrayType *b)
51 int num = ARRNELEMS(b);
52 int32 *ptr = ARRPTR(b);
58 if (GETBIT(GETSIGN(a), HASHVAL(*ptr)))
67 _intbig_contains(GISTTYPE *a, ArrayType *b)
69 int num = ARRNELEMS(b);
70 int32 *ptr = ARRPTR(b);
76 if (!GETBIT(GETSIGN(a), HASHVAL(*ptr)))
85 g_intbig_same(PG_FUNCTION_ARGS)
87 GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
88 GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
89 bool *result = (bool *) PG_GETARG_POINTER(2);
91 if (ISALLTRUE(a) && ISALLTRUE(b))
93 else if (ISALLTRUE(a))
95 else if (ISALLTRUE(b))
100 BITVECP sa = GETSIGN(a),
113 PG_RETURN_POINTER(result);
117 g_intbig_compress(PG_FUNCTION_ARGS)
119 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
124 ArrayType *in = DatumGetArrayTypeP(entry->key);
127 GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
140 SET_VARSIZE(res, CALCGTSIZE(0));
144 HASH(GETSIGN(res), *ptr);
148 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
149 gistentryinit(*retval, PointerGetDatum(res),
150 entry->rel, entry->page,
151 entry->offset, false);
153 if (in != DatumGetArrayTypeP(entry->key))
156 PG_RETURN_POINTER(retval);
158 else if (!ISALLTRUE(DatumGetPointer(entry->key)))
162 BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
167 if ((sign[i] & 0xff) != 0xff)
168 PG_RETURN_POINTER(entry);
171 res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE));
172 SET_VARSIZE(res, CALCGTSIZE(ALLISTRUE));
173 res->flag = ALLISTRUE;
175 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
176 gistentryinit(*retval, PointerGetDatum(res),
177 entry->rel, entry->page,
178 entry->offset, false);
180 PG_RETURN_POINTER(retval);
183 PG_RETURN_POINTER(entry);
188 sizebitvec(BITVECP sign)
190 return pg_popcount(sign, SIGLEN);
194 hemdistsign(BITVECP a, BITVECP b)
202 diff = (unsigned char) (a[i] ^ b[i]);
203 /* Using the popcount functions here isn't likely to win */
204 dist += pg_number_of_ones[diff];
210 hemdist(GISTTYPE *a, GISTTYPE *b)
217 return SIGLENBIT - sizebitvec(GETSIGN(b));
219 else if (ISALLTRUE(b))
220 return SIGLENBIT - sizebitvec(GETSIGN(a));
222 return hemdistsign(GETSIGN(a), GETSIGN(b));
226 g_intbig_decompress(PG_FUNCTION_ARGS)
228 PG_RETURN_DATUM(PG_GETARG_DATUM(0));
232 unionkey(BITVECP sbase, GISTTYPE *add)
235 BITVECP sadd = GETSIGN(add);
245 g_intbig_union(PG_FUNCTION_ARGS)
247 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
248 int *size = (int *) PG_GETARG_POINTER(1);
255 MemSet((void *) base, 0, sizeof(BITVEC));
256 for (i = 0; i < entryvec->n; i++)
258 if (unionkey(base, GETENTRY(entryvec, i)))
265 len = CALCGTSIZE(flag);
266 result = (GISTTYPE *) palloc(len);
267 SET_VARSIZE(result, len);
269 if (!ISALLTRUE(result))
270 memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));
273 PG_RETURN_POINTER(result);
277 g_intbig_penalty(PG_FUNCTION_ARGS)
279 GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
280 GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
281 float *penalty = (float *) PG_GETARG_POINTER(2);
282 GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
283 GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
285 *penalty = hemdist(origval, newval);
286 PG_RETURN_POINTER(penalty);
297 comparecost(const void *a, const void *b)
299 return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
304 g_intbig_picksplit(PG_FUNCTION_ARGS)
306 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
307 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
319 OffsetNumber seed_1 = 0,
326 SPLITCOST *costvector;
330 maxoff = entryvec->n - 2;
331 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
332 v->spl_left = (OffsetNumber *) palloc(nbytes);
333 v->spl_right = (OffsetNumber *) palloc(nbytes);
335 for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
337 _k = GETENTRY(entryvec, k);
338 for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
340 size_waste = hemdist(_k, GETENTRY(entryvec, j));
341 if (size_waste > waste)
352 right = v->spl_right;
355 if (seed_1 == 0 || seed_2 == 0)
361 /* form initial .. */
362 if (ISALLTRUE(GETENTRY(entryvec, seed_1)))
364 datum_l = (GISTTYPE *) palloc(GTHDRSIZE);
365 SET_VARSIZE(datum_l, GTHDRSIZE);
366 datum_l->flag = ALLISTRUE;
370 datum_l = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
371 SET_VARSIZE(datum_l, GTHDRSIZE + SIGLEN);
373 memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), sizeof(BITVEC));
375 if (ISALLTRUE(GETENTRY(entryvec, seed_2)))
377 datum_r = (GISTTYPE *) palloc(GTHDRSIZE);
378 SET_VARSIZE(datum_r, GTHDRSIZE);
379 datum_r->flag = ALLISTRUE;
383 datum_r = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
384 SET_VARSIZE(datum_r, GTHDRSIZE + SIGLEN);
386 memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), sizeof(BITVEC));
389 maxoff = OffsetNumberNext(maxoff);
390 /* sort before ... */
391 costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
392 for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
394 costvector[j - 1].pos = j;
395 _j = GETENTRY(entryvec, j);
396 size_alpha = hemdist(datum_l, _j);
397 size_beta = hemdist(datum_r, _j);
398 costvector[j - 1].cost = Abs(size_alpha - size_beta);
400 qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
402 union_l = GETSIGN(datum_l);
403 union_r = GETSIGN(datum_r);
405 for (k = 0; k < maxoff; k++)
407 j = costvector[k].pos;
414 else if (j == seed_2)
420 _j = GETENTRY(entryvec, j);
421 size_alpha = hemdist(datum_l, _j);
422 size_beta = hemdist(datum_r, _j);
424 if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
426 if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
428 if (!ISALLTRUE(datum_l))
429 MemSet((void *) union_l, 0xff, sizeof(BITVEC));
435 union_l[i] |= ptr[i];
442 if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
444 if (!ISALLTRUE(datum_r))
445 MemSet((void *) union_r, 0xff, sizeof(BITVEC));
451 union_r[i] |= ptr[i];
458 *right = *left = FirstOffsetNumber;
461 v->spl_ldatum = PointerGetDatum(datum_l);
462 v->spl_rdatum = PointerGetDatum(datum_r);
464 PG_RETURN_POINTER(v);
468 g_intbig_consistent(PG_FUNCTION_ARGS)
470 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
471 ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
472 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
474 /* Oid subtype = PG_GETARG_OID(3); */
475 bool *recheck = (bool *) PG_GETARG_POINTER(4);
478 /* All cases served by this function are inexact */
481 if (ISALLTRUE(DatumGetPointer(entry->key)))
482 PG_RETURN_BOOL(true);
484 if (strategy == BooleanSearchStrategy)
486 retval = signconsistent((QUERYTYPE *) query,
487 GETSIGN(DatumGetPointer(entry->key)),
489 PG_FREE_IF_COPY(query, 1);
490 PG_RETURN_BOOL(retval);
493 CHECKARRVALID(query);
497 case RTOverlapStrategyNumber:
498 retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
500 case RTSameStrategyNumber:
501 if (GIST_LEAF(entry))
504 num = ARRNELEMS(query);
505 int32 *ptr = ARRPTR(query);
510 memset(qp, 0, sizeof(BITVEC));
518 de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
532 retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
534 case RTContainsStrategyNumber:
535 case RTOldContainsStrategyNumber:
536 retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
538 case RTContainedByStrategyNumber:
539 case RTOldContainedByStrategyNumber:
540 if (GIST_LEAF(entry))
543 num = ARRNELEMS(query);
544 int32 *ptr = ARRPTR(query);
549 memset(qp, 0, sizeof(BITVEC));
557 de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
572 * Unfortunately, because empty arrays could be anywhere in
573 * the index, we must search the whole tree.
581 PG_FREE_IF_COPY(query, 1);
582 PG_RETURN_BOOL(retval);