PostgreSQL Source Code git master
Loading...
Searching...
No Matches
_ltree_gist.c
Go to the documentation of this file.
1/*
2 * contrib/ltree/_ltree_gist.c
3 *
4 *
5 * GiST support for ltree[]
6 * Teodor Sigaev <teodor@stack.net>
7 */
8#include "postgres.h"
9
10#include "access/gist.h"
11#include "access/reloptions.h"
12#include "access/stratnum.h"
13#include "crc32.h"
14#include "ltree.h"
15#include "port/pg_bitutils.h"
16#include "utils/array.h"
17
25
26#define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
27#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
28
29#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
30
31
32static void
33hashing(BITVECP sign, ltree *t, int siglen)
34{
35 int tlen = t->numlevel;
37 int hash;
38
39 while (tlen > 0)
40 {
41 hash = ltree_crc32_sz(cur->name, cur->len);
42 AHASH(sign, hash, siglen);
44 tlen--;
45 }
46}
47
50{
52 GISTENTRY *retval = entry;
53 int siglen = LTREE_GET_ASIGLEN();
54
55 if (entry->leafkey)
56 { /* ltree */
57 ltree_gist *key;
60 ltree *item = (ltree *) ARR_DATA_PTR(val);
61
62 if (ARR_NDIM(val) > 1)
65 errmsg("array must be one-dimensional")));
69 errmsg("array must not contain nulls")));
70
71 key = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
72
73 while (num > 0)
74 {
75 hashing(LTG_SIGN(key), item, siglen);
76 num--;
77 item = NEXTVAL(item);
78 }
79
80 retval = palloc_object(GISTENTRY);
81 gistentryinit(*retval, PointerGetDatum(key),
82 entry->rel, entry->page,
83 entry->offset, false);
84 }
85 else if (!LTG_ISALLTRUE(DatumGetPointer(entry->key)))
86 {
87 int32 i;
88 ltree_gist *key;
90
91 ALOOPBYTE(siglen)
92 {
93 if ((sign[i] & 0xff) != 0xff)
94 PG_RETURN_POINTER(retval);
95 }
96
97 key = ltree_gist_alloc(true, sign, siglen, NULL, NULL);
98 retval = palloc_object(GISTENTRY);
99 gistentryinit(*retval, PointerGetDatum(key),
100 entry->rel, entry->page,
101 entry->offset, false);
102 }
103 PG_RETURN_POINTER(retval);
104}
105
106Datum
108{
111 bool *result = (bool *) PG_GETARG_POINTER(2);
112 int siglen = LTREE_GET_ASIGLEN();
113
115 *result = true;
116 else if (LTG_ISALLTRUE(a))
117 *result = false;
118 else if (LTG_ISALLTRUE(b))
119 *result = false;
120 else
121 {
122 int32 i;
123 BITVECP sa = LTG_SIGN(a),
124 sb = LTG_SIGN(b);
125
126 *result = true;
127 ALOOPBYTE(siglen)
128 {
129 if (sa[i] != sb[i])
130 {
131 *result = false;
132 break;
133 }
134 }
135 }
136 PG_RETURN_POINTER(result);
137}
138
139static int32
141{
142 int32 i;
144
145 if (LTG_ISALLTRUE(add))
146 return 1;
147
148 ALOOPBYTE(siglen)
149 sbase[i] |= sadd[i];
150 return 0;
151}
152
153Datum
155{
157 int *size = (int *) PG_GETARG_POINTER(1);
158 int siglen = LTREE_GET_ASIGLEN();
159 int32 i;
160 ltree_gist *result = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
161 BITVECP base = LTG_SIGN(result);
162
163 for (i = 0; i < entryvec->n; i++)
164 {
165 if (unionkey(base, GETENTRY(entryvec, i), siglen))
166 {
167 result->flag |= LTG_ALLTRUE;
168 SET_VARSIZE(result, LTG_HDRSIZE);
169 break;
170 }
171 }
172
173 *size = VARSIZE(result);
174
175 PG_RETURN_POINTER(result);
176}
177
178static int32
180{
181 return pg_popcount((const char *) sign, siglen);
182}
183
184static int
186{
187 int i,
188 diff,
189 dist = 0;
190
191 ALOOPBYTE(siglen)
192 {
193 diff = (unsigned char) (a[i] ^ b[i]);
194 /* Using the popcount functions here isn't likely to win */
196 }
197 return dist;
198}
199
200static int
202{
203 if (LTG_ISALLTRUE(a))
204 {
205 if (LTG_ISALLTRUE(b))
206 return 0;
207 else
208 return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(b), siglen);
209 }
210 else if (LTG_ISALLTRUE(b))
211 return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(a), siglen);
212
213 return hemdistsign(LTG_SIGN(a), LTG_SIGN(b), siglen);
214}
215
216
217Datum
219{
222 float *penalty = (float *) PG_GETARG_POINTER(2);
223 int siglen = LTREE_GET_ASIGLEN();
224
225 *penalty = hemdist(origval, newval, siglen);
226 PG_RETURN_POINTER(penalty);
227}
228
229typedef struct
230{
231 OffsetNumber pos;
232 int32 cost;
233} SPLITCOST;
234
235static int
236comparecost(const void *a, const void *b)
237{
238 return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
239}
240
241Datum
243{
246 int siglen = LTREE_GET_ASIGLEN();
247 OffsetNumber k,
248 j;
250 *datum_r;
252 union_r;
254 size_beta;
256 waste = -1;
257 int32 nbytes;
259 seed_2 = 0;
260 OffsetNumber *left,
261 *right;
262 OffsetNumber maxoff;
263 BITVECP ptr;
264 int i;
266 ltree_gist *_k,
267 *_j;
268
269 maxoff = entryvec->n - 2;
270 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
271 v->spl_left = (OffsetNumber *) palloc(nbytes);
272 v->spl_right = (OffsetNumber *) palloc(nbytes);
273
274 for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
275 {
276 _k = GETENTRY(entryvec, k);
277 for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
278 {
279 size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
280 if (size_waste > waste)
281 {
282 waste = size_waste;
283 seed_1 = k;
284 seed_2 = j;
285 }
286 }
287 }
288
289 left = v->spl_left;
290 v->spl_nleft = 0;
291 right = v->spl_right;
292 v->spl_nright = 0;
293
294 if (seed_1 == 0 || seed_2 == 0)
295 {
296 seed_1 = 1;
297 seed_2 = 2;
298 }
299
300 /* form initial .. */
303 siglen, NULL, NULL);
304
307 siglen, NULL, NULL);
308
309 maxoff = OffsetNumberNext(maxoff);
310 /* sort before ... */
312 for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
313 {
314 costvector[j - 1].pos = j;
315 _j = GETENTRY(entryvec, j);
316 size_alpha = hemdist(datum_l, _j, siglen);
317 size_beta = hemdist(datum_r, _j, siglen);
318 costvector[j - 1].cost = abs(size_alpha - size_beta);
319 }
320 qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
321
324
325 for (k = 0; k < maxoff; k++)
326 {
327 j = costvector[k].pos;
328 if (j == seed_1)
329 {
330 *left++ = j;
331 v->spl_nleft++;
332 continue;
333 }
334 else if (j == seed_2)
335 {
336 *right++ = j;
337 v->spl_nright++;
338 continue;
339 }
340 _j = GETENTRY(entryvec, j);
341 size_alpha = hemdist(datum_l, _j, siglen);
342 size_beta = hemdist(datum_r, _j, siglen);
343
344 if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
345 {
347 {
349 memset(union_l, 0xff, siglen);
350 }
351 else
352 {
353 ptr = LTG_SIGN(_j);
354 ALOOPBYTE(siglen)
355 union_l[i] |= ptr[i];
356 }
357 *left++ = j;
358 v->spl_nleft++;
359 }
360 else
361 {
363 {
365 memset(union_r, 0xff, siglen);
366 }
367 else
368 {
369 ptr = LTG_SIGN(_j);
370 ALOOPBYTE(siglen)
371 union_r[i] |= ptr[i];
372 }
373 *right++ = j;
374 v->spl_nright++;
375 }
376 }
377
378 *right = *left = FirstOffsetNumber;
379
382
384}
385
386static bool
387gist_te(ltree_gist *key, ltree *query, int siglen)
388{
389 ltree_level *curq = LTREE_FIRST(query);
390 BITVECP sign = LTG_SIGN(key);
391 int qlen = query->numlevel;
392 unsigned int hv;
393
394 if (LTG_ISALLTRUE(key))
395 return true;
396
397 while (qlen > 0)
398 {
399 hv = ltree_crc32_sz(curq->name, curq->len);
400 if (!GETBIT(sign, AHASHVAL(hv, siglen)))
401 return false;
403 qlen--;
404 }
405
406 return true;
407}
408
414
415static bool
417{
418 LtreeSignature *sig = cxt;
419
420 return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(sig->sign, AHASHVAL(val->val, sig->siglen)) : true;
421}
422
423static bool
424gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
425{
427
428 if (LTG_ISALLTRUE(key))
429 return true;
430
431 sig.sign = LTG_SIGN(key);
432 sig.siglen = siglen;
433
434 return ltree_execute(GETQUERY(query),
435 &sig, false,
437}
438
439static bool
440gist_qe(ltree_gist *key, lquery *query, int siglen)
441{
443 BITVECP sign = LTG_SIGN(key);
444 int qlen = query->numlevel;
445
446 if (LTG_ISALLTRUE(key))
447 return true;
448
449 while (qlen > 0)
450 {
451 if (curq->numvar && LQL_CANLOOKSIGN(curq))
452 {
453 bool isexist = false;
454 int vlen = curq->numvar;
456
457 while (vlen > 0)
458 {
459 if (GETBIT(sign, AHASHVAL(curv->val, siglen)))
460 {
461 isexist = true;
462 break;
463 }
465 vlen--;
466 }
467 if (!isexist)
468 return false;
469 }
470
471 curq = LQL_NEXT(curq);
472 qlen--;
473 }
474
475 return true;
476}
477
478static bool
480{
481 lquery *query = (lquery *) ARR_DATA_PTR(_query);
483
484 if (ARR_NDIM(_query) > 1)
487 errmsg("array must be one-dimensional")));
491 errmsg("array must not contain nulls")));
492
493 while (num > 0)
494 {
495 if (gist_qe(key, query, siglen))
496 return true;
497 num--;
498 query = (lquery *) NEXTVAL(query);
499 }
500 return false;
501}
502
503Datum
505{
506 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
507 void *query = PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
509#ifdef NOT_USED
510 Oid subtype = PG_GETARG_OID(3);
511#endif
512 bool *recheck = (bool *) PG_GETARG_POINTER(4);
513 int siglen = LTREE_GET_ASIGLEN();
514 ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
515 bool res = false;
516
517 /* All cases served by this function are inexact */
518 *recheck = true;
519
520 switch (strategy)
521 {
522 case 10:
523 case 11:
524 res = gist_te(key, (ltree *) query, siglen);
525 break;
526 case 12:
527 case 13:
528 res = gist_qe(key, (lquery *) query, siglen);
529 break;
530 case 14:
531 case 15:
532 res = gist_qtxt(key, (ltxtquery *) query, siglen);
533 break;
534 case 16:
535 case 17:
536 res = _arrq_cons(key, (ArrayType *) query, siglen);
537 break;
538 default:
539 /* internal error */
540 elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
541 }
542 PG_FREE_IF_COPY(query, 1);
543 PG_RETURN_BOOL(res);
544}
545
546Datum
#define GETQUERY(x)
Definition _int.h:157
#define NEXTVAL(x)
Definition _ltree_gist.c:27
static bool gist_qe(ltree_gist *key, lquery *query, int siglen)
#define WISH_F(a, b, c)
Definition _ltree_gist.c:29
static bool _arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
static bool gist_te(ltree_gist *key, ltree *query, int siglen)
static void hashing(BITVECP sign, ltree *t, int siglen)
Definition _ltree_gist.c:33
static int32 sizebitvec(BITVECP sign, int siglen)
static int hemdistsign(BITVECP a, BITVECP b, int siglen)
Datum _ltree_union(PG_FUNCTION_ARGS)
#define GETENTRY(vec, pos)
Definition _ltree_gist.c:26
Datum _ltree_penalty(PG_FUNCTION_ARGS)
static bool gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
static int hemdist(ltree_gist *a, ltree_gist *b, int siglen)
static int32 unionkey(BITVECP sbase, ltree_gist *add, int siglen)
struct LtreeSignature LtreeSignature
Datum _ltree_gist_options(PG_FUNCTION_ARGS)
static bool checkcondition_bit(void *cxt, ITEM *val)
Datum _ltree_compress(PG_FUNCTION_ARGS)
Definition _ltree_gist.c:49
Datum _ltree_consistent(PG_FUNCTION_ARGS)
Datum _ltree_same(PG_FUNCTION_ARGS)
Datum _ltree_picksplit(PG_FUNCTION_ARGS)
static int comparecost(const void *a, const void *b)
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_DIMS(a)
Definition array.h:294
bool array_contains_nulls(const ArrayType *array)
int ArrayGetNItems(int ndim, const int *dims)
Definition arrayutils.c:57
#define GETBIT(x, i)
Definition blutils.c:30
int32_t int32
Definition c.h:542
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition crc32.c:22
struct cursor * cur
Definition ecpg.c:29
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#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_OID(n)
Definition fmgr.h:275
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_GETARG_UINT16(n)
Definition fmgr.h:272
#define PG_DETOAST_DATUM(datum)
Definition fmgr.h:240
#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 gistentryinit(e, k, r, pg, o, l)
Definition gist.h:245
#define newval
char * BITVECP
Definition hstore_gist.c:31
long val
Definition informix.c:689
char sign
Definition informix.c:693
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
#define LTG_HDRSIZE
Definition ltree.h:280
#define FLG_CANLOOKSIGN(x)
Definition ltree.h:107
#define LTREE_FIRST(x)
Definition ltree.h:51
#define AHASHVAL(val, siglen)
Definition ltree.h:308
#define LTREE_GET_ASIGLEN()
Definition ltree.h:300
#define LTG_ALLTRUE
Definition ltree.h:277
#define LEVEL_NEXT(x)
Definition ltree.h:40
#define ASIGLENBIT(siglen)
Definition ltree.h:303
#define LTREE_ASIGLEN_MAX
Definition ltree.h:299
#define ALOOPBYTE(siglen)
Definition ltree.h:305
bool ltree_execute(ITEM *curitem, void *checkval, bool calcnot, bool(*chkcond)(void *checkval, ITEM *val))
#define LQL_CANLOOKSIGN(x)
Definition ltree.h:111
#define LQL_FIRST(x)
Definition ltree.h:101
#define AHASH(sign, val, siglen)
Definition ltree.h:309
#define LVAR_NEXT(x)
Definition ltree.h:72
#define LQL_NEXT(x)
Definition ltree.h:100
#define LQUERY_FIRST(x)
Definition ltree.h:124
#define LTG_ISALLTRUE(x)
Definition ltree.h:284
#define LTG_SIGN(x)
Definition ltree.h:281
ltree_gist * ltree_gist_alloc(bool isalltrue, BITVECP sign, int siglen, ltree *left, ltree *right)
Definition ltree_gist.c:42
#define LTREE_ASIGLEN_DEFAULT
Definition ltree.h:298
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:80
static uint64 pg_popcount(const char *buf, int bytes)
static int sig
Definition pg_ctl.c:81
#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
unsigned int Oid
static int fb(int x)
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:715
void init_local_reloptions(local_relopts *relopts, Size relopt_struct_size)
Definition reloptions.c:782
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)
uint16 StrategyNumber
Definition stratnum.h:22
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
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
Definition _int.h:141
char * name
Definition type.h:139
uint16 numlevel
Definition ltree.h:116
uint32 flag
Definition ltree.h:272
Definition ltree.h:43
uint16 numlevel
Definition ltree.h:45
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432