2 * contrib/intarray/_intbig_gist.c
7 #include "access/gist.h"
8 #include "access/stratnum.h"
9 #include "port/pg_bitutils.h"
11 #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
15 PG_FUNCTION_INFO_V1(g_intbig_consistent);
16 PG_FUNCTION_INFO_V1(g_intbig_compress);
17 PG_FUNCTION_INFO_V1(g_intbig_decompress);
18 PG_FUNCTION_INFO_V1(g_intbig_penalty);
19 PG_FUNCTION_INFO_V1(g_intbig_picksplit);
20 PG_FUNCTION_INFO_V1(g_intbig_union);
21 PG_FUNCTION_INFO_V1(g_intbig_same);
22 PG_FUNCTION_INFO_V1(_intbig_in);
23 PG_FUNCTION_INFO_V1(_intbig_out);
26 _intbig_in(PG_FUNCTION_ARGS)
29 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
30 errmsg("_intbig_in() not implemented")));
35 _intbig_out(PG_FUNCTION_ARGS)
38 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
39 errmsg("_intbig_out() not implemented")));
44 /*********************************************************************
46 *********************************************************************/
48 _intbig_overlap(GISTTYPE *a, ArrayType *b)
50 int num = ARRNELEMS(b);
51 int32 *ptr = ARRPTR(b);
57 if (GETBIT(GETSIGN(a), HASHVAL(*ptr)))
66 _intbig_contains(GISTTYPE *a, ArrayType *b)
68 int num = ARRNELEMS(b);
69 int32 *ptr = ARRPTR(b);
75 if (!GETBIT(GETSIGN(a), HASHVAL(*ptr)))
84 g_intbig_same(PG_FUNCTION_ARGS)
86 GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
87 GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
88 bool *result = (bool *) PG_GETARG_POINTER(2);
90 if (ISALLTRUE(a) && ISALLTRUE(b))
92 else if (ISALLTRUE(a))
94 else if (ISALLTRUE(b))
99 BITVECP sa = GETSIGN(a),
112 PG_RETURN_POINTER(result);
116 g_intbig_compress(PG_FUNCTION_ARGS)
118 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
123 ArrayType *in = DatumGetArrayTypeP(entry->key);
126 GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
139 SET_VARSIZE(res, CALCGTSIZE(0));
143 HASH(GETSIGN(res), *ptr);
147 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
148 gistentryinit(*retval, PointerGetDatum(res),
149 entry->rel, entry->page,
150 entry->offset, false);
152 if (in != DatumGetArrayTypeP(entry->key))
155 PG_RETURN_POINTER(retval);
157 else if (!ISALLTRUE(DatumGetPointer(entry->key)))
161 BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
166 if ((sign[i] & 0xff) != 0xff)
167 PG_RETURN_POINTER(entry);
170 res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE));
171 SET_VARSIZE(res, CALCGTSIZE(ALLISTRUE));
172 res->flag = ALLISTRUE;
174 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
175 gistentryinit(*retval, PointerGetDatum(res),
176 entry->rel, entry->page,
177 entry->offset, false);
179 PG_RETURN_POINTER(retval);
182 PG_RETURN_POINTER(entry);
187 sizebitvec(BITVECP sign)
189 return pg_popcount(sign, SIGLEN);
193 hemdistsign(BITVECP a, BITVECP b)
201 diff = (unsigned char) (a[i] ^ b[i]);
202 /* Using the popcount functions here isn't likely to win */
203 dist += pg_number_of_ones[diff];
209 hemdist(GISTTYPE *a, GISTTYPE *b)
216 return SIGLENBIT - sizebitvec(GETSIGN(b));
218 else if (ISALLTRUE(b))
219 return SIGLENBIT - sizebitvec(GETSIGN(a));
221 return hemdistsign(GETSIGN(a), GETSIGN(b));
225 g_intbig_decompress(PG_FUNCTION_ARGS)
227 PG_RETURN_DATUM(PG_GETARG_DATUM(0));
231 unionkey(BITVECP sbase, GISTTYPE *add)
234 BITVECP sadd = GETSIGN(add);
244 g_intbig_union(PG_FUNCTION_ARGS)
246 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
247 int *size = (int *) PG_GETARG_POINTER(1);
254 MemSet((void *) base, 0, sizeof(BITVEC));
255 for (i = 0; i < entryvec->n; i++)
257 if (unionkey(base, GETENTRY(entryvec, i)))
264 len = CALCGTSIZE(flag);
265 result = (GISTTYPE *) palloc(len);
266 SET_VARSIZE(result, len);
268 if (!ISALLTRUE(result))
269 memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));
272 PG_RETURN_POINTER(result);
276 g_intbig_penalty(PG_FUNCTION_ARGS)
278 GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
279 GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
280 float *penalty = (float *) PG_GETARG_POINTER(2);
281 GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
282 GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
284 *penalty = hemdist(origval, newval);
285 PG_RETURN_POINTER(penalty);
296 comparecost(const void *a, const void *b)
298 return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
303 g_intbig_picksplit(PG_FUNCTION_ARGS)
305 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
306 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
318 OffsetNumber seed_1 = 0,
325 SPLITCOST *costvector;
329 maxoff = entryvec->n - 2;
330 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
331 v->spl_left = (OffsetNumber *) palloc(nbytes);
332 v->spl_right = (OffsetNumber *) palloc(nbytes);
334 for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
336 _k = GETENTRY(entryvec, k);
337 for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
339 size_waste = hemdist(_k, GETENTRY(entryvec, j));
340 if (size_waste > waste)
351 right = v->spl_right;
354 if (seed_1 == 0 || seed_2 == 0)
360 /* form initial .. */
361 if (ISALLTRUE(GETENTRY(entryvec, seed_1)))
363 datum_l = (GISTTYPE *) palloc(GTHDRSIZE);
364 SET_VARSIZE(datum_l, GTHDRSIZE);
365 datum_l->flag = ALLISTRUE;
369 datum_l = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
370 SET_VARSIZE(datum_l, GTHDRSIZE + SIGLEN);
372 memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), sizeof(BITVEC));
374 if (ISALLTRUE(GETENTRY(entryvec, seed_2)))
376 datum_r = (GISTTYPE *) palloc(GTHDRSIZE);
377 SET_VARSIZE(datum_r, GTHDRSIZE);
378 datum_r->flag = ALLISTRUE;
382 datum_r = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
383 SET_VARSIZE(datum_r, GTHDRSIZE + SIGLEN);
385 memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), sizeof(BITVEC));
388 maxoff = OffsetNumberNext(maxoff);
389 /* sort before ... */
390 costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
391 for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
393 costvector[j - 1].pos = j;
394 _j = GETENTRY(entryvec, j);
395 size_alpha = hemdist(datum_l, _j);
396 size_beta = hemdist(datum_r, _j);
397 costvector[j - 1].cost = Abs(size_alpha - size_beta);
399 qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
401 union_l = GETSIGN(datum_l);
402 union_r = GETSIGN(datum_r);
404 for (k = 0; k < maxoff; k++)
406 j = costvector[k].pos;
413 else if (j == seed_2)
419 _j = GETENTRY(entryvec, j);
420 size_alpha = hemdist(datum_l, _j);
421 size_beta = hemdist(datum_r, _j);
423 if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
425 if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
427 if (!ISALLTRUE(datum_l))
428 MemSet((void *) union_l, 0xff, sizeof(BITVEC));
434 union_l[i] |= ptr[i];
441 if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
443 if (!ISALLTRUE(datum_r))
444 MemSet((void *) union_r, 0xff, sizeof(BITVEC));
450 union_r[i] |= ptr[i];
457 *right = *left = FirstOffsetNumber;
460 v->spl_ldatum = PointerGetDatum(datum_l);
461 v->spl_rdatum = PointerGetDatum(datum_r);
463 PG_RETURN_POINTER(v);
467 g_intbig_consistent(PG_FUNCTION_ARGS)
469 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
470 ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
471 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
473 /* Oid subtype = PG_GETARG_OID(3); */
474 bool *recheck = (bool *) PG_GETARG_POINTER(4);
477 /* All cases served by this function are inexact */
480 if (ISALLTRUE(DatumGetPointer(entry->key)))
481 PG_RETURN_BOOL(true);
483 if (strategy == BooleanSearchStrategy)
485 retval = signconsistent((QUERYTYPE *) query,
486 GETSIGN(DatumGetPointer(entry->key)),
488 PG_FREE_IF_COPY(query, 1);
489 PG_RETURN_BOOL(retval);
492 CHECKARRVALID(query);
496 case RTOverlapStrategyNumber:
497 retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
499 case RTSameStrategyNumber:
500 if (GIST_LEAF(entry))
503 num = ARRNELEMS(query);
504 int32 *ptr = ARRPTR(query);
509 memset(qp, 0, sizeof(BITVEC));
517 de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
531 retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
533 case RTContainsStrategyNumber:
534 case RTOldContainsStrategyNumber:
535 retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
537 case RTContainedByStrategyNumber:
538 case RTOldContainedByStrategyNumber:
539 if (GIST_LEAF(entry))
542 num = ARRNELEMS(query);
543 int32 *ptr = ARRPTR(query);
548 memset(qp, 0, sizeof(BITVEC));
556 de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
571 * Unfortunately, because empty arrays could be anywhere in
572 * the index, we must search the whole tree.
580 PG_FREE_IF_COPY(query, 1);
581 PG_RETURN_BOOL(retval);