5
#include "access/gist.h"
6
#include "access/itup.h"
7
#include "access/rtree.h"
8
#include "utils/array.h"
9
#include "utils/builtins.h"
10
#include "storage/bufpage.h"
11
#include "access/tuptoaster.h"
18
PG_FUNCTION_INFO_V1(gtxtidx_in);
19
Datum gtxtidx_in(PG_FUNCTION_ARGS);
21
PG_FUNCTION_INFO_V1(gtxtidx_out);
22
Datum gtxtidx_out(PG_FUNCTION_ARGS);
24
PG_FUNCTION_INFO_V1(gtxtidx_compress);
25
Datum gtxtidx_compress(PG_FUNCTION_ARGS);
27
PG_FUNCTION_INFO_V1(gtxtidx_decompress);
28
Datum gtxtidx_decompress(PG_FUNCTION_ARGS);
30
PG_FUNCTION_INFO_V1(gtxtidx_consistent);
31
Datum gtxtidx_consistent(PG_FUNCTION_ARGS);
33
PG_FUNCTION_INFO_V1(gtxtidx_union);
34
Datum gtxtidx_union(PG_FUNCTION_ARGS);
36
PG_FUNCTION_INFO_V1(gtxtidx_same);
37
Datum gtxtidx_same(PG_FUNCTION_ARGS);
39
PG_FUNCTION_INFO_V1(gtxtidx_penalty);
40
Datum gtxtidx_penalty(PG_FUNCTION_ARGS);
42
PG_FUNCTION_INFO_V1(gtxtidx_picksplit);
43
Datum gtxtidx_picksplit(PG_FUNCTION_ARGS);
45
#define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
46
#define SUMBIT(val) ( \
59
gtxtidx_in(PG_FUNCTION_ARGS)
62
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
63
errmsg("gtxtidx_in not implemented")));
68
gtxtidx_out(PG_FUNCTION_ARGS)
71
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
72
errmsg("gtxtidx_out not implemented")));
77
compareint(const void *a, const void *b)
79
if (*((int4 *) a) == *((int4 *) b))
81
return (*((int4 *) a) > *((int4 *) b)) ? 1 : -1;
85
uniqueint(int4 *a, int4 l)
95
qsort((void *) a, l, sizeof(int4), compareint);
106
makesign(BITVECP sign, GISTTYPE * a)
110
int4 *ptr = GETARR(a);
112
MemSet((void *) sign, 0, sizeof(BITVEC));
113
for (k = 0; k < len; k++)
118
gtxtidx_compress(PG_FUNCTION_ARGS)
120
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
121
GISTENTRY *retval = entry;
126
txtidx *toastedval = (txtidx *) DatumGetPointer(entry->key);
127
txtidx *val = (txtidx *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
130
WordEntry *ptr = ARRPTR(val);
131
char *words = STRPTR(val);
133
len = CALCGTSIZE(ARRKEY, val->size);
134
res = (GISTTYPE *) palloc(len);
141
*arr = crc32_sz((uint8 *) &words[ptr->pos], ptr->len);
146
len = uniqueint(GETARR(res), val->size);
147
if (len != val->size)
150
* there is a collision of hash-function; len is always less
153
len = CALCGTSIZE(ARRKEY, len);
154
res = (GISTTYPE *) repalloc((void *) res, len);
157
if (val != toastedval)
160
/* make signature, if array is too long */
161
if (res->len > TOAST_INDEX_TARGET)
165
len = CALCGTSIZE(SIGNKEY, 0);
166
ressign = (GISTTYPE *) palloc(len);
168
ressign->flag = SIGNKEY;
169
makesign(GETSIGN(ressign), res);
174
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
175
gistentryinit(*retval, PointerGetDatum(res),
176
entry->rel, entry->page,
177
entry->offset, res->len, FALSE);
179
else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
180
!ISALLTRUE(DatumGetPointer(entry->key)))
185
BITVECP sign = GETSIGN(DatumGetPointer(entry->key));
188
if ((sign[i] & 0xff) != 0xff)
189
PG_RETURN_POINTER(retval);
192
len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
193
res = (GISTTYPE *) palloc(len);
195
res->flag = SIGNKEY | ALLISTRUE;
197
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
198
gistentryinit(*retval, PointerGetDatum(res),
199
entry->rel, entry->page,
200
entry->offset, res->len, FALSE);
202
PG_RETURN_POINTER(retval);
206
gtxtidx_decompress(PG_FUNCTION_ARGS)
208
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
209
GISTTYPE *key = (GISTTYPE *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
211
if (key != (GISTTYPE *) DatumGetPointer(entry->key))
213
GISTENTRY *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
215
gistentryinit(*retval, PointerGetDatum(key),
216
entry->rel, entry->page,
217
entry->offset, key->len, FALSE);
219
PG_RETURN_POINTER(retval);
222
PG_RETURN_POINTER(entry);
232
* is there value 'val' in array or not ?
235
checkcondition_arr(void *checkval, ITEM * val)
237
int4 *StopLow = ((CHKVAL *) checkval)->arrb;
238
int4 *StopHigh = ((CHKVAL *) checkval)->arre;
241
/* Loop invariant: StopLow <= val < StopHigh */
243
while (StopLow < StopHigh)
245
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
246
if (*StopMiddle == val->val)
248
else if (*StopMiddle < val->val)
249
StopLow = StopMiddle + 1;
251
StopHigh = StopMiddle;
258
checkcondition_bit(void *checkval, ITEM * val)
260
return GETBIT(checkval, HASHVAL(val->val));
264
gtxtidx_consistent(PG_FUNCTION_ARGS)
266
QUERYTYPE *query = (QUERYTYPE *) PG_GETARG_POINTER(1);
267
GISTTYPE *key = (GISTTYPE *) DatumGetPointer(
268
((GISTENTRY *) PG_GETARG_POINTER(0))->key
272
PG_RETURN_BOOL(false);
277
PG_RETURN_BOOL(true);
279
PG_RETURN_BOOL(execute(
281
(void *) GETSIGN(key), false,
286
{ /* only leaf pages */
289
chkval.arrb = GETARR(key);
290
chkval.arre = chkval.arrb + ARRNELEM(key);
291
PG_RETURN_BOOL(execute(
293
(void *) &chkval, true,
300
unionkey(BITVECP sbase, GISTTYPE * add)
306
BITVECP sadd = GETSIGN(add);
317
int4 *ptr = GETARR(add);
319
for (i = 0; i < ARRNELEM(add); i++)
327
gtxtidx_union(PG_FUNCTION_ARGS)
329
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
330
int *size = (int *) PG_GETARG_POINTER(1);
337
MemSet((void *) base, 0, sizeof(BITVEC));
338
for (i = 0; i < entryvec->n; i++)
340
if (unionkey(base, GETENTRY(entryvec, i)))
348
len = CALCGTSIZE(flag, 0);
349
result = (GISTTYPE *) palloc(len);
350
*size = result->len = len;
352
if (!ISALLTRUE(result))
353
memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));
355
PG_RETURN_POINTER(result);
359
gtxtidx_same(PG_FUNCTION_ARGS)
361
GISTTYPE *a = (GISTTYPE *) PG_GETARG_POINTER(0);
362
GISTTYPE *b = (GISTTYPE *) PG_GETARG_POINTER(1);
363
bool *result = (bool *) PG_GETARG_POINTER(2);
366
{ /* then b also ISSIGNKEY */
367
if (ISALLTRUE(a) && ISALLTRUE(b))
369
else if (ISALLTRUE(a))
371
else if (ISALLTRUE(b))
376
BITVECP sa = GETSIGN(a),
390
{ /* a and b ISARRKEY */
391
int4 lena = ARRNELEM(a),
398
int4 *ptra = GETARR(a),
403
for (i = 0; i < lena; i++)
404
if (ptra[i] != ptrb[i])
412
PG_RETURN_POINTER(result);
416
sizebitvec(BITVECP sign)
422
size += SUMBIT(*(char *) sign);
423
sign = (BITVECP) (((char *) sign) + 1);
429
gtxtidx_penalty(PG_FUNCTION_ARGS)
431
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
432
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
433
float *penalty = (float *) PG_GETARG_POINTER(2);
434
GISTTYPE *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
435
GISTTYPE *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
437
BITVECP orig = GETSIGN(origval);
439
if (ISALLTRUE(origval))
442
PG_RETURN_POINTER(penalty);
445
if (ISARRKEY(newval))
447
int4 *ptr = GETARR(newval),
448
n = ARRNELEM(newval);
452
if (GETBIT(orig, HASHVAL(*ptr)) == 0)
456
*penalty = (float) unionsize;
460
if (ISALLTRUE(newval))
461
*penalty = (float) (SIGLENBIT - sizebitvec(orig));
465
BITVECP nval = GETSIGN(newval);
469
valtmp = nval[i] | orig[i];
470
unionsize += SUMBIT(valtmp) - SUMBIT(orig[i]);
472
*penalty = (float) unionsize;
476
PG_RETURN_POINTER(penalty);
486
fillcache(CACHESIGN * item, GISTTYPE * key)
488
item->allistrue = false;
490
makesign(item->sign, key);
491
else if (ISALLTRUE(key))
492
item->allistrue = true;
494
memcpy((void *) item->sign, (void *) GETSIGN(key), sizeof(BITVEC));
497
#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
505
comparecost(const void *a, const void *b)
507
if (((SPLITCOST *) a)->cost == ((SPLITCOST *) b)->cost)
510
return (((SPLITCOST *) a)->cost > ((SPLITCOST *) b)->cost) ? 1 : -1;
514
gtxtidx_picksplit(PG_FUNCTION_ARGS)
516
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
517
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
524
bool firsttime = true;
534
OffsetNumber seed_1 = 0,
545
SPLITCOST *costvector;
547
maxoff = entryvec->n - 2;
548
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
549
v->spl_left = (OffsetNumber *) palloc(nbytes);
550
v->spl_right = (OffsetNumber *) palloc(nbytes);
552
cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
553
fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));
555
for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
557
for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
559
if (k == FirstOffsetNumber)
560
fillcache(&cache[j], GETENTRY(entryvec, j));
562
if (cache[k].allistrue || cache[j].allistrue)
565
if (cache[k].allistrue && cache[j].allistrue)
568
sizei = (cache[k].allistrue) ?
569
sizebitvec(cache[j].sign) : sizebitvec(cache[k].sign);
574
ptra = cache[j].sign;
575
ptrb = cache[k].sign;
576
/* critical section for bench !!! */
578
#define COUNT(pos) do { \
579
if ( GETBITBYTE(*(char*)ptra,pos) ) { \
581
if ( GETBITBYTE(*(char*)ptrb, pos) ) \
583
} else if ( GETBITBYTE(*(char*)ptrb, pos) ) \
595
ptra = (BITVECP) (((char *) ptra) + 1);
596
ptrb = (BITVECP) (((char *) ptrb) + 1);
600
size_waste = sizeu - sizei;
601
if (size_waste > waste || firsttime)
613
right = v->spl_right;
616
if (seed_1 == 0 || seed_2 == 0)
622
/* form initial .. */
623
if (cache[seed_1].allistrue)
625
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
626
datum_l->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
627
datum_l->flag = SIGNKEY | ALLISTRUE;
632
datum_l = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
633
datum_l->len = CALCGTSIZE(SIGNKEY, 0);
634
datum_l->flag = SIGNKEY;
635
memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
636
size_l = sizebitvec(GETSIGN(datum_l));
638
if (cache[seed_2].allistrue)
640
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
641
datum_r->len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
642
datum_r->flag = SIGNKEY | ALLISTRUE;
647
datum_r = (GISTTYPE *) palloc(CALCGTSIZE(SIGNKEY, 0));
648
datum_r->len = CALCGTSIZE(SIGNKEY, 0);
649
datum_r->flag = SIGNKEY;
650
memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
651
size_r = sizebitvec(GETSIGN(datum_r));
654
maxoff = OffsetNumberNext(maxoff);
655
fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
656
/* sort before ... */
657
costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
658
for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
660
costvector[j - 1].pos = j;
661
if (cache[j].allistrue)
663
size_alpha = SIGLENBIT - size_l;
664
size_beta = SIGLENBIT - size_r;
668
ptra = cache[seed_1].sign;
669
ptrb = cache[seed_2].sign;
670
ptrc = cache[j].sign;
671
size_beta = size_alpha = 0;
672
if (cache[seed_1].allistrue)
674
if (!cache[seed_2].allistrue)
677
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
682
else if (cache[seed_2].allistrue)
684
if (!cache[seed_1].allistrue)
687
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
695
if (GETBIT(ptrc, i) && !GETBIT(ptra, i))
697
if (GETBIT(ptrc, i) && !GETBIT(ptrb, i))
703
costvector[j - 1].cost = Abs(size_alpha - size_beta);
705
qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
707
for (k = 0; k < maxoff; k++)
709
j = costvector[k].pos;
716
else if (j == seed_2)
723
if (ISALLTRUE(datum_l) || cache[j].allistrue)
724
size_alpha = SIGLENBIT;
727
ptra = cache[j].sign;
728
ptrb = GETSIGN(datum_l);
731
valtmp = union_l[i] = ptra[i] | ptrb[i];
732
size_alpha += SUMBIT(valtmp);
735
if (ISALLTRUE(datum_r) || cache[j].allistrue)
736
size_beta = SIGLENBIT;
739
ptra = cache[j].sign;
740
ptrb = GETSIGN(datum_r);
743
valtmp = union_r[i] = ptra[i] | ptrb[i];
744
size_beta += SUMBIT(valtmp);
748
if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
750
if (!ISALLTRUE(datum_l))
752
if (size_alpha == SIGLENBIT)
754
if (size_alpha != size_l)
755
MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
758
memcpy((void *) GETSIGN(datum_l), (void *) union_l, sizeof(BITVEC));
766
if (!ISALLTRUE(datum_r))
768
if (size_beta == SIGLENBIT)
770
if (size_beta != size_r)
771
MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
774
memcpy((void *) GETSIGN(datum_r), (void *) union_r, sizeof(BITVEC));
782
*right = *left = FirstOffsetNumber;
785
v->spl_ldatum = PointerGetDatum(datum_l);
786
v->spl_rdatum = PointerGetDatum(datum_r);
788
PG_RETURN_POINTER(v);