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