6 #include "access/gist.h"
7 #include "access/skey.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
);
23 Datum
g_intbig_consistent(PG_FUNCTION_ARGS
);
24 Datum
g_intbig_compress(PG_FUNCTION_ARGS
);
25 Datum
g_intbig_decompress(PG_FUNCTION_ARGS
);
26 Datum
g_intbig_penalty(PG_FUNCTION_ARGS
);
27 Datum
g_intbig_picksplit(PG_FUNCTION_ARGS
);
28 Datum
g_intbig_union(PG_FUNCTION_ARGS
);
29 Datum
g_intbig_same(PG_FUNCTION_ARGS
);
31 /* Number of one-bits in an unsigned byte */
32 static const uint8 number_of_ones
[256] = {
33 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
34 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
35 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
36 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
37 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
38 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
39 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
40 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
41 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
42 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
43 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
44 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
45 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
46 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
47 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
48 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
51 PG_FUNCTION_INFO_V1(_intbig_in
);
52 Datum
_intbig_in(PG_FUNCTION_ARGS
);
54 PG_FUNCTION_INFO_V1(_intbig_out
);
55 Datum
_intbig_out(PG_FUNCTION_ARGS
);
59 _intbig_in(PG_FUNCTION_ARGS
)
62 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
63 errmsg("_intbig_in() not implemented")));
68 _intbig_out(PG_FUNCTION_ARGS
)
71 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
72 errmsg("_intbig_out() not implemented")));
77 /*********************************************************************
79 *********************************************************************/
81 _intbig_overlap(GISTTYPE
* a
, ArrayType
*b
)
83 int num
= ARRNELEMS(b
);
84 int4
*ptr
= ARRPTR(b
);
90 if (GETBIT(GETSIGN(a
), HASHVAL(*ptr
)))
99 _intbig_contains(GISTTYPE
* a
, ArrayType
*b
)
101 int num
= ARRNELEMS(b
);
102 int4
*ptr
= ARRPTR(b
);
108 if (!GETBIT(GETSIGN(a
), HASHVAL(*ptr
)))
117 g_intbig_same(PG_FUNCTION_ARGS
)
119 GISTTYPE
*a
= (GISTTYPE
*) PG_GETARG_POINTER(0);
120 GISTTYPE
*b
= (GISTTYPE
*) PG_GETARG_POINTER(1);
121 bool *result
= (bool *) PG_GETARG_POINTER(2);
123 if (ISALLTRUE(a
) && ISALLTRUE(b
))
125 else if (ISALLTRUE(a
))
127 else if (ISALLTRUE(b
))
132 BITVECP sa
= GETSIGN(a
),
145 PG_RETURN_POINTER(result
);
149 g_intbig_compress(PG_FUNCTION_ARGS
)
151 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
156 ArrayType
*in
= (ArrayType
*) PG_DETOAST_DATUM(entry
->key
);
159 GISTTYPE
*res
= (GISTTYPE
*) palloc0(CALCGTSIZE(0));
172 SET_VARSIZE(res
, CALCGTSIZE(0));
176 HASH(GETSIGN(res
), *ptr
);
180 retval
= (GISTENTRY
*) palloc(sizeof(GISTENTRY
));
181 gistentryinit(*retval
, PointerGetDatum(res
),
182 entry
->rel
, entry
->page
,
183 entry
->offset
, FALSE
);
185 if (in
!= (ArrayType
*) PG_DETOAST_DATUM(entry
->key
))
188 PG_RETURN_POINTER(retval
);
190 else if (!ISALLTRUE(DatumGetPointer(entry
->key
)))
194 BITVECP sign
= GETSIGN(DatumGetPointer(entry
->key
));
199 if ((sign
[i
] & 0xff) != 0xff)
200 PG_RETURN_POINTER(entry
);
203 res
= (GISTTYPE
*) palloc(CALCGTSIZE(ALLISTRUE
));
204 SET_VARSIZE(res
, CALCGTSIZE(ALLISTRUE
));
205 res
->flag
= ALLISTRUE
;
207 retval
= (GISTENTRY
*) palloc(sizeof(GISTENTRY
));
208 gistentryinit(*retval
, PointerGetDatum(res
),
209 entry
->rel
, entry
->page
,
210 entry
->offset
, FALSE
);
212 PG_RETURN_POINTER(retval
);
215 PG_RETURN_POINTER(entry
);
220 sizebitvec(BITVECP sign
)
226 size
+= number_of_ones
[(unsigned char) sign
[i
]];
231 hemdistsign(BITVECP a
, BITVECP b
)
239 diff
= (unsigned char) (a
[i
] ^ b
[i
]);
240 dist
+= number_of_ones
[diff
];
246 hemdist(GISTTYPE
* a
, GISTTYPE
* b
)
253 return SIGLENBIT
- sizebitvec(GETSIGN(b
));
255 else if (ISALLTRUE(b
))
256 return SIGLENBIT
- sizebitvec(GETSIGN(a
));
258 return hemdistsign(GETSIGN(a
), GETSIGN(b
));
262 g_intbig_decompress(PG_FUNCTION_ARGS
)
264 PG_RETURN_DATUM(PG_GETARG_DATUM(0));
268 unionkey(BITVECP sbase
, GISTTYPE
* add
)
271 BITVECP sadd
= GETSIGN(add
);
281 g_intbig_union(PG_FUNCTION_ARGS
)
283 GistEntryVector
*entryvec
= (GistEntryVector
*) PG_GETARG_POINTER(0);
284 int *size
= (int *) PG_GETARG_POINTER(1);
291 MemSet((void *) base
, 0, sizeof(BITVEC
));
292 for (i
= 0; i
< entryvec
->n
; i
++)
294 if (unionkey(base
, GETENTRY(entryvec
, i
)))
301 len
= CALCGTSIZE(flag
);
302 result
= (GISTTYPE
*) palloc(len
);
303 SET_VARSIZE(result
, len
);
305 if (!ISALLTRUE(result
))
306 memcpy((void *) GETSIGN(result
), (void *) base
, sizeof(BITVEC
));
309 PG_RETURN_POINTER(result
);
313 g_intbig_penalty(PG_FUNCTION_ARGS
)
315 GISTENTRY
*origentry
= (GISTENTRY
*) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
316 GISTENTRY
*newentry
= (GISTENTRY
*) PG_GETARG_POINTER(1);
317 float *penalty
= (float *) PG_GETARG_POINTER(2);
318 GISTTYPE
*origval
= (GISTTYPE
*) DatumGetPointer(origentry
->key
);
319 GISTTYPE
*newval
= (GISTTYPE
*) DatumGetPointer(newentry
->key
);
321 *penalty
= hemdist(origval
, newval
);
322 PG_RETURN_POINTER(penalty
);
333 comparecost(const void *a
, const void *b
)
335 return ((SPLITCOST
*) a
)->cost
- ((SPLITCOST
*) b
)->cost
;
340 g_intbig_picksplit(PG_FUNCTION_ARGS
)
342 GistEntryVector
*entryvec
= (GistEntryVector
*) PG_GETARG_POINTER(0);
343 GIST_SPLITVEC
*v
= (GIST_SPLITVEC
*) PG_GETARG_POINTER(1);
355 OffsetNumber seed_1
= 0,
362 SPLITCOST
*costvector
;
366 maxoff
= entryvec
->n
- 2;
367 nbytes
= (maxoff
+ 2) * sizeof(OffsetNumber
);
368 v
->spl_left
= (OffsetNumber
*) palloc(nbytes
);
369 v
->spl_right
= (OffsetNumber
*) palloc(nbytes
);
371 for (k
= FirstOffsetNumber
; k
< maxoff
; k
= OffsetNumberNext(k
))
373 _k
= GETENTRY(entryvec
, k
);
374 for (j
= OffsetNumberNext(k
); j
<= maxoff
; j
= OffsetNumberNext(j
))
376 size_waste
= hemdist(_k
, GETENTRY(entryvec
, j
));
377 if (size_waste
> waste
)
388 right
= v
->spl_right
;
391 if (seed_1
== 0 || seed_2
== 0)
397 /* form initial .. */
398 if (ISALLTRUE(GETENTRY(entryvec
, seed_1
)))
400 datum_l
= (GISTTYPE
*) palloc(GTHDRSIZE
);
401 SET_VARSIZE(datum_l
, GTHDRSIZE
);
402 datum_l
->flag
= ALLISTRUE
;
406 datum_l
= (GISTTYPE
*) palloc(GTHDRSIZE
+ SIGLEN
);
407 SET_VARSIZE(datum_l
, GTHDRSIZE
+ SIGLEN
);
409 memcpy((void *) GETSIGN(datum_l
), (void *) GETSIGN(GETENTRY(entryvec
, seed_1
)), sizeof(BITVEC
));
411 if (ISALLTRUE(GETENTRY(entryvec
, seed_2
)))
413 datum_r
= (GISTTYPE
*) palloc(GTHDRSIZE
);
414 SET_VARSIZE(datum_r
, GTHDRSIZE
);
415 datum_r
->flag
= ALLISTRUE
;
419 datum_r
= (GISTTYPE
*) palloc(GTHDRSIZE
+ SIGLEN
);
420 SET_VARSIZE(datum_r
, GTHDRSIZE
+ SIGLEN
);
422 memcpy((void *) GETSIGN(datum_r
), (void *) GETSIGN(GETENTRY(entryvec
, seed_2
)), sizeof(BITVEC
));
425 maxoff
= OffsetNumberNext(maxoff
);
426 /* sort before ... */
427 costvector
= (SPLITCOST
*) palloc(sizeof(SPLITCOST
) * maxoff
);
428 for (j
= FirstOffsetNumber
; j
<= maxoff
; j
= OffsetNumberNext(j
))
430 costvector
[j
- 1].pos
= j
;
431 _j
= GETENTRY(entryvec
, j
);
432 size_alpha
= hemdist(datum_l
, _j
);
433 size_beta
= hemdist(datum_r
, _j
);
434 costvector
[j
- 1].cost
= Abs(size_alpha
- size_beta
);
436 qsort((void *) costvector
, maxoff
, sizeof(SPLITCOST
), comparecost
);
438 union_l
= GETSIGN(datum_l
);
439 union_r
= GETSIGN(datum_r
);
441 for (k
= 0; k
< maxoff
; k
++)
443 j
= costvector
[k
].pos
;
450 else if (j
== seed_2
)
456 _j
= GETENTRY(entryvec
, j
);
457 size_alpha
= hemdist(datum_l
, _j
);
458 size_beta
= hemdist(datum_r
, _j
);
460 if (size_alpha
< size_beta
+ WISH_F(v
->spl_nleft
, v
->spl_nright
, 0.00001))
462 if (ISALLTRUE(datum_l
) || ISALLTRUE(_j
))
464 if (!ISALLTRUE(datum_l
))
465 MemSet((void *) union_l
, 0xff, sizeof(BITVEC
));
471 union_l
[i
] |= ptr
[i
];
478 if (ISALLTRUE(datum_r
) || ISALLTRUE(_j
))
480 if (!ISALLTRUE(datum_r
))
481 MemSet((void *) union_r
, 0xff, sizeof(BITVEC
));
487 union_r
[i
] |= ptr
[i
];
494 *right
= *left
= FirstOffsetNumber
;
497 v
->spl_ldatum
= PointerGetDatum(datum_l
);
498 v
->spl_rdatum
= PointerGetDatum(datum_r
);
500 PG_RETURN_POINTER(v
);
504 g_intbig_consistent(PG_FUNCTION_ARGS
)
506 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
507 ArrayType
*query
= (ArrayType
*) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
508 StrategyNumber strategy
= (StrategyNumber
) PG_GETARG_UINT16(2);
509 /* Oid subtype = PG_GETARG_OID(3); */
510 bool *recheck
= (bool *) PG_GETARG_POINTER(4);
513 /* All cases served by this function are inexact */
516 if (ISALLTRUE(DatumGetPointer(entry
->key
)))
517 PG_RETURN_BOOL(true);
519 if (strategy
== BooleanSearchStrategy
)
521 retval
= signconsistent((QUERYTYPE
*) query
,
522 GETSIGN(DatumGetPointer(entry
->key
)),
524 PG_FREE_IF_COPY(query
, 1);
525 PG_RETURN_BOOL(retval
);
528 CHECKARRVALID(query
);
529 if (ARRISVOID(query
))
531 PG_FREE_IF_COPY(query
, 1);
532 PG_RETURN_BOOL(FALSE
);
537 case RTOverlapStrategyNumber
:
538 retval
= _intbig_overlap((GISTTYPE
*) DatumGetPointer(entry
->key
), query
);
540 case RTSameStrategyNumber
:
541 if (GIST_LEAF(entry
))
544 num
= ARRNELEMS(query
);
545 int4
*ptr
= ARRPTR(query
);
550 CHECKARRVALID(query
);
552 memset(qp
, 0, sizeof(BITVEC
));
560 de
= GETSIGN((GISTTYPE
*) DatumGetPointer(entry
->key
));
574 retval
= _intbig_contains((GISTTYPE
*) DatumGetPointer(entry
->key
), query
);
576 case RTContainsStrategyNumber
:
577 case RTOldContainsStrategyNumber
:
578 retval
= _intbig_contains((GISTTYPE
*) DatumGetPointer(entry
->key
), query
);
580 case RTContainedByStrategyNumber
:
581 case RTOldContainedByStrategyNumber
:
582 if (GIST_LEAF(entry
))
585 num
= ARRNELEMS(query
);
586 int4
*ptr
= ARRPTR(query
);
591 CHECKARRVALID(query
);
593 memset(qp
, 0, sizeof(BITVEC
));
601 de
= GETSIGN((GISTTYPE
*) DatumGetPointer(entry
->key
));
614 retval
= _intbig_overlap((GISTTYPE
*) DatumGetPointer(entry
->key
), query
);
619 PG_FREE_IF_COPY(query
, 1);
620 PG_RETURN_BOOL(retval
);