PostgreSQL Source Code  git master
tsgistidx.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * tsgistidx.c
4  * GiST support functions for tsvector_ops
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/tsgistidx.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include "access/gist.h"
18 #include "access/heaptoast.h"
19 #include "access/reloptions.h"
20 #include "lib/qunique.h"
21 #include "port/pg_bitutils.h"
22 #include "tsearch/ts_utils.h"
23 #include "utils/builtins.h"
24 #include "utils/pg_crc.h"
25 
26 
27 /* tsvector_ops opclass options */
28 typedef struct
29 {
30  int32 vl_len_; /* varlena header (do not touch directly!) */
31  int siglen; /* signature length */
33 
34 #define SIGLEN_DEFAULT (31 * 4)
35 #define SIGLEN_MAX GISTMaxIndexKeySize
36 #define GET_SIGLEN() (PG_HAS_OPCLASS_OPTIONS() ? \
37  ((GistTsVectorOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
38  SIGLEN_DEFAULT)
39 
40 #define SIGLENBIT(siglen) ((siglen) * BITS_PER_BYTE)
41 
42 typedef char *BITVECP;
43 
44 #define LOOPBYTE(siglen) \
45  for (i = 0; i < siglen; i++)
46 
47 #define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITS_PER_BYTE ) ) )
48 #define GETBITBYTE(x,i) ( ((char)(x)) >> (i) & 0x01 )
49 #define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITS_PER_BYTE ) )
50 #define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITS_PER_BYTE ) )
51 #define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITS_PER_BYTE )) & 0x01 )
52 
53 #define HASHVAL(val, siglen) (((unsigned int)(val)) % SIGLENBIT(siglen))
54 #define HASH(sign, val, siglen) SETBIT((sign), HASHVAL(val, siglen))
55 
56 #define GETENTRY(vec,pos) ((SignTSVector *) DatumGetPointer((vec)->vector[(pos)].key))
57 
58 /*
59  * type of GiST index key
60  */
61 
62 typedef struct
63 {
64  int32 vl_len_; /* varlena header (do not touch directly!) */
67 } SignTSVector;
68 
69 #define ARRKEY 0x01
70 #define SIGNKEY 0x02
71 #define ALLISTRUE 0x04
72 
73 #define ISARRKEY(x) ( ((SignTSVector*)(x))->flag & ARRKEY )
74 #define ISSIGNKEY(x) ( ((SignTSVector*)(x))->flag & SIGNKEY )
75 #define ISALLTRUE(x) ( ((SignTSVector*)(x))->flag & ALLISTRUE )
76 
77 #define GTHDRSIZE ( VARHDRSZ + sizeof(int32) )
78 #define CALCGTSIZE(flag, len) ( GTHDRSIZE + ( ( (flag) & ARRKEY ) ? ((len)*sizeof(int32)) : (((flag) & ALLISTRUE) ? 0 : (len)) ) )
79 
80 #define GETSIGN(x) ( (BITVECP)( (char*)(x)+GTHDRSIZE ) )
81 #define GETSIGLEN(x)( VARSIZE(x) - GTHDRSIZE )
82 #define GETARR(x) ( (int32*)( (char*)(x)+GTHDRSIZE ) )
83 #define ARRNELEM(x) ( ( VARSIZE(x) - GTHDRSIZE )/sizeof(int32) )
84 
85 static int32 sizebitvec(BITVECP sign, int siglen);
86 
87 Datum
89 {
90  ereport(ERROR,
91  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
92  errmsg("gtsvector_in not implemented")));
93  PG_RETURN_DATUM(0);
94 }
95 
96 #define SINGOUTSTR "%d true bits, %d false bits"
97 #define ARROUTSTR "%d unique words"
98 #define EXTRALEN ( 2*13 )
99 
100 static int outbuf_maxlen = 0;
101 
102 Datum
104 {
106  char *outbuf;
107 
108  if (outbuf_maxlen == 0)
109  outbuf_maxlen = 2 * EXTRALEN + Max(strlen(SINGOUTSTR), strlen(ARROUTSTR)) + 1;
110  outbuf = palloc(outbuf_maxlen);
111 
112  if (ISARRKEY(key))
113  sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key));
114  else
115  {
116  int siglen = GETSIGLEN(key);
117  int cnttrue = (ISALLTRUE(key)) ? SIGLENBIT(siglen) : sizebitvec(GETSIGN(key), siglen);
118 
119  sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT(siglen) - cnttrue);
120  }
121 
122  PG_FREE_IF_COPY(key, 0);
123  PG_RETURN_POINTER(outbuf);
124 }
125 
126 static int
127 compareint(const void *va, const void *vb)
128 {
129  int32 a = *((const int32 *) va);
130  int32 b = *((const int32 *) vb);
131 
132  if (a == b)
133  return 0;
134  return (a > b) ? 1 : -1;
135 }
136 
137 static void
139 {
140  int32 k,
141  len = ARRNELEM(a);
142  int32 *ptr = GETARR(a);
143 
144  MemSet((void *) sign, 0, siglen);
145  for (k = 0; k < len; k++)
146  HASH(sign, ptr[k], siglen);
147 }
148 
149 static SignTSVector *
151 {
152  int size = CALCGTSIZE(flag, len);
153  SignTSVector *res = palloc(size);
154 
155  SET_VARSIZE(res, size);
156  res->flag = flag;
157 
158  if ((flag & (SIGNKEY | ALLISTRUE)) == SIGNKEY && sign)
159  memcpy(GETSIGN(res), sign, len);
160 
161  return res;
162 }
163 
164 
165 Datum
167 {
168  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
169  int siglen = GET_SIGLEN();
170  GISTENTRY *retval = entry;
171 
172  if (entry->leafkey)
173  { /* tsvector */
174  TSVector val = DatumGetTSVector(entry->key);
175  SignTSVector *res = gtsvector_alloc(ARRKEY, val->size, NULL);
176  int32 len;
177  int32 *arr;
178  WordEntry *ptr = ARRPTR(val);
179  char *words = STRPTR(val);
180 
181  arr = GETARR(res);
182  len = val->size;
183  while (len--)
184  {
185  pg_crc32 c;
186 
188  COMP_LEGACY_CRC32(c, words + ptr->pos, ptr->len);
189  FIN_LEGACY_CRC32(c);
190 
191  *arr = *(int32 *) &c;
192  arr++;
193  ptr++;
194  }
195 
196  qsort(GETARR(res), val->size, sizeof(int), compareint);
197  len = qunique(GETARR(res), val->size, sizeof(int), compareint);
198  if (len != val->size)
199  {
200  /*
201  * there is a collision of hash-function; len is always less than
202  * val->size
203  */
204  len = CALCGTSIZE(ARRKEY, len);
205  res = (SignTSVector *) repalloc((void *) res, len);
206  SET_VARSIZE(res, len);
207  }
208 
209  /* make signature, if array is too long */
210  if (VARSIZE(res) > TOAST_INDEX_TARGET)
211  {
212  SignTSVector *ressign = gtsvector_alloc(SIGNKEY, siglen, NULL);
213 
214  makesign(GETSIGN(ressign), res, siglen);
215  res = ressign;
216  }
217 
218  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
219  gistentryinit(*retval, PointerGetDatum(res),
220  entry->rel, entry->page,
221  entry->offset, false);
222  }
223  else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
224  !ISALLTRUE(DatumGetPointer(entry->key)))
225  {
226  int32 i;
227  SignTSVector *res;
229 
230  LOOPBYTE(siglen)
231  {
232  if ((sign[i] & 0xff) != 0xff)
233  PG_RETURN_POINTER(retval);
234  }
235 
236  res = gtsvector_alloc(SIGNKEY | ALLISTRUE, siglen, sign);
237  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
238  gistentryinit(*retval, PointerGetDatum(res),
239  entry->rel, entry->page,
240  entry->offset, false);
241  }
242  PG_RETURN_POINTER(retval);
243 }
244 
245 Datum
247 {
248  /*
249  * We need to detoast the stored value, because the other gtsvector
250  * support functions don't cope with toasted values.
251  */
252  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
254 
255  if (key != (SignTSVector *) DatumGetPointer(entry->key))
256  {
257  GISTENTRY *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
258 
259  gistentryinit(*retval, PointerGetDatum(key),
260  entry->rel, entry->page,
261  entry->offset, false);
262 
263  PG_RETURN_POINTER(retval);
264  }
265 
266  PG_RETURN_POINTER(entry);
267 }
268 
269 typedef struct
270 {
271  int32 *arrb;
272  int32 *arre;
273 } CHKVAL;
274 
275 /*
276  * TS_execute callback for matching a tsquery operand to GIST leaf-page data
277  */
278 static TSTernaryValue
280 {
281  int32 *StopLow = ((CHKVAL *) checkval)->arrb;
282  int32 *StopHigh = ((CHKVAL *) checkval)->arre;
283  int32 *StopMiddle;
284 
285  /* Loop invariant: StopLow <= val < StopHigh */
286 
287  /*
288  * we are not able to find a prefix by hash value
289  */
290  if (val->prefix)
291  return TS_MAYBE;
292 
293  while (StopLow < StopHigh)
294  {
295  StopMiddle = StopLow + (StopHigh - StopLow) / 2;
296  if (*StopMiddle == val->valcrc)
297  return TS_MAYBE;
298  else if (*StopMiddle < val->valcrc)
299  StopLow = StopMiddle + 1;
300  else
301  StopHigh = StopMiddle;
302  }
303 
304  return TS_NO;
305 }
306 
307 /*
308  * TS_execute callback for matching a tsquery operand to GIST non-leaf data
309  */
310 static TSTernaryValue
312 {
313  void *key = (SignTSVector *) checkval;
314 
315  /*
316  * we are not able to find a prefix in signature tree
317  */
318  if (val->prefix)
319  return TS_MAYBE;
320 
321  if (GETBIT(GETSIGN(key), HASHVAL(val->valcrc, GETSIGLEN(key))))
322  return TS_MAYBE;
323  else
324  return TS_NO;
325 }
326 
327 Datum
329 {
330  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
331  TSQuery query = PG_GETARG_TSQUERY(1);
332 
333  /* StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); */
334  /* Oid subtype = PG_GETARG_OID(3); */
335  bool *recheck = (bool *) PG_GETARG_POINTER(4);
337 
338  /* All cases served by this function are inexact */
339  *recheck = true;
340 
341  if (!query->size)
342  PG_RETURN_BOOL(false);
343 
344  if (ISSIGNKEY(key))
345  {
346  if (ISALLTRUE(key))
347  PG_RETURN_BOOL(true);
348 
350  key,
353  }
354  else
355  { /* only leaf pages */
356  CHKVAL chkval;
357 
358  chkval.arrb = GETARR(key);
359  chkval.arre = chkval.arrb + ARRNELEM(key);
361  (void *) &chkval,
364  }
365 }
366 
367 static int32
368 unionkey(BITVECP sbase, SignTSVector *add, int siglen)
369 {
370  int32 i;
371 
372  if (ISSIGNKEY(add))
373  {
374  BITVECP sadd = GETSIGN(add);
375 
376  if (ISALLTRUE(add))
377  return 1;
378 
379  Assert(GETSIGLEN(add) == siglen);
380 
381  LOOPBYTE(siglen)
382  sbase[i] |= sadd[i];
383  }
384  else
385  {
386  int32 *ptr = GETARR(add);
387 
388  for (i = 0; i < ARRNELEM(add); i++)
389  HASH(sbase, ptr[i], siglen);
390  }
391  return 0;
392 }
393 
394 
395 Datum
397 {
399  int *size = (int *) PG_GETARG_POINTER(1);
400  int siglen = GET_SIGLEN();
401  SignTSVector *result = gtsvector_alloc(SIGNKEY, siglen, NULL);
402  BITVECP base = GETSIGN(result);
403  int32 i;
404 
405  memset(base, 0, siglen);
406 
407  for (i = 0; i < entryvec->n; i++)
408  {
409  if (unionkey(base, GETENTRY(entryvec, i), siglen))
410  {
411  result->flag |= ALLISTRUE;
412  SET_VARSIZE(result, CALCGTSIZE(result->flag, siglen));
413  break;
414  }
415  }
416 
417  *size = VARSIZE(result);
418 
419  PG_RETURN_POINTER(result);
420 }
421 
422 Datum
424 {
427  bool *result = (bool *) PG_GETARG_POINTER(2);
428  int siglen = GET_SIGLEN();
429 
430  if (ISSIGNKEY(a))
431  { /* then b also ISSIGNKEY */
432  if (ISALLTRUE(a) && ISALLTRUE(b))
433  *result = true;
434  else if (ISALLTRUE(a))
435  *result = false;
436  else if (ISALLTRUE(b))
437  *result = false;
438  else
439  {
440  int32 i;
441  BITVECP sa = GETSIGN(a),
442  sb = GETSIGN(b);
443 
444  Assert(GETSIGLEN(a) == siglen && GETSIGLEN(b) == siglen);
445 
446  *result = true;
447  LOOPBYTE(siglen)
448  {
449  if (sa[i] != sb[i])
450  {
451  *result = false;
452  break;
453  }
454  }
455  }
456  }
457  else
458  { /* a and b ISARRKEY */
459  int32 lena = ARRNELEM(a),
460  lenb = ARRNELEM(b);
461 
462  if (lena != lenb)
463  *result = false;
464  else
465  {
466  int32 *ptra = GETARR(a),
467  *ptrb = GETARR(b);
468  int32 i;
469 
470  *result = true;
471  for (i = 0; i < lena; i++)
472  if (ptra[i] != ptrb[i])
473  {
474  *result = false;
475  break;
476  }
477  }
478  }
479 
480  PG_RETURN_POINTER(result);
481 }
482 
483 static int32
484 sizebitvec(BITVECP sign, int siglen)
485 {
486  return pg_popcount(sign, siglen);
487 }
488 
489 static int
490 hemdistsign(BITVECP a, BITVECP b, int siglen)
491 {
492  int i,
493  diff,
494  dist = 0;
495 
496  LOOPBYTE(siglen)
497  {
498  diff = (unsigned char) (a[i] ^ b[i]);
499  /* Using the popcount functions here isn't likely to win */
500  dist += pg_number_of_ones[diff];
501  }
502  return dist;
503 }
504 
505 static int
507 {
508  int siglena = GETSIGLEN(a);
509  int siglenb = GETSIGLEN(b);
510 
511  if (ISALLTRUE(a))
512  {
513  if (ISALLTRUE(b))
514  return 0;
515  else
516  return SIGLENBIT(siglenb) - sizebitvec(GETSIGN(b), siglenb);
517  }
518  else if (ISALLTRUE(b))
519  return SIGLENBIT(siglena) - sizebitvec(GETSIGN(a), siglena);
520 
521  Assert(siglena == siglenb);
522 
523  return hemdistsign(GETSIGN(a), GETSIGN(b), siglena);
524 }
525 
526 Datum
528 {
529  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
530  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
531  float *penalty = (float *) PG_GETARG_POINTER(2);
532  int siglen = GET_SIGLEN();
533  SignTSVector *origval = (SignTSVector *) DatumGetPointer(origentry->key);
535  BITVECP orig = GETSIGN(origval);
536 
537  *penalty = 0.0;
538 
539  if (ISARRKEY(newval))
540  {
541  BITVECP sign = palloc(siglen);
542 
543  makesign(sign, newval, siglen);
544 
545  if (ISALLTRUE(origval))
546  {
547  int siglenbit = SIGLENBIT(siglen);
548 
549  *penalty =
550  (float) (siglenbit - sizebitvec(sign, siglen)) /
551  (float) (siglenbit + 1);
552  }
553  else
554  *penalty = hemdistsign(sign, orig, siglen);
555 
556  pfree(sign);
557  }
558  else
559  *penalty = hemdist(origval, newval);
560  PG_RETURN_POINTER(penalty);
561 }
562 
563 typedef struct
564 {
565  bool allistrue;
566  BITVECP sign;
567 } CACHESIGN;
568 
569 static void
570 fillcache(CACHESIGN *item, SignTSVector *key, int siglen)
571 {
572  item->allistrue = false;
573  if (ISARRKEY(key))
574  makesign(item->sign, key, siglen);
575  else if (ISALLTRUE(key))
576  item->allistrue = true;
577  else
578  memcpy((void *) item->sign, (void *) GETSIGN(key), siglen);
579 }
580 
581 #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
582 typedef struct
583 {
584  OffsetNumber pos;
585  int32 cost;
586 } SPLITCOST;
587 
588 static int
589 comparecost(const void *va, const void *vb)
590 {
591  const SPLITCOST *a = (const SPLITCOST *) va;
592  const SPLITCOST *b = (const SPLITCOST *) vb;
593 
594  if (a->cost == b->cost)
595  return 0;
596  else
597  return (a->cost > b->cost) ? 1 : -1;
598 }
599 
600 
601 static int
602 hemdistcache(CACHESIGN *a, CACHESIGN *b, int siglen)
603 {
604  if (a->allistrue)
605  {
606  if (b->allistrue)
607  return 0;
608  else
609  return SIGLENBIT(siglen) - sizebitvec(b->sign, siglen);
610  }
611  else if (b->allistrue)
612  return SIGLENBIT(siglen) - sizebitvec(a->sign, siglen);
613 
614  return hemdistsign(a->sign, b->sign, siglen);
615 }
616 
617 Datum
619 {
622  int siglen = GET_SIGLEN();
623  OffsetNumber k,
624  j;
625  SignTSVector *datum_l,
626  *datum_r;
627  BITVECP union_l,
628  union_r;
629  int32 size_alpha,
630  size_beta;
631  int32 size_waste,
632  waste = -1;
633  int32 nbytes;
634  OffsetNumber seed_1 = 0,
635  seed_2 = 0;
636  OffsetNumber *left,
637  *right;
638  OffsetNumber maxoff;
639  BITVECP ptr;
640  int i;
641  CACHESIGN *cache;
642  char *cache_sign;
643  SPLITCOST *costvector;
644 
645  maxoff = entryvec->n - 2;
646  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
647  v->spl_left = (OffsetNumber *) palloc(nbytes);
648  v->spl_right = (OffsetNumber *) palloc(nbytes);
649 
650  cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
651  cache_sign = palloc(siglen * (maxoff + 2));
652 
653  for (j = 0; j < maxoff + 2; j++)
654  cache[j].sign = &cache_sign[siglen * j];
655 
656  fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber),
657  siglen);
658 
659  for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
660  {
661  for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
662  {
663  if (k == FirstOffsetNumber)
664  fillcache(&cache[j], GETENTRY(entryvec, j), siglen);
665 
666  size_waste = hemdistcache(&(cache[j]), &(cache[k]), siglen);
667  if (size_waste > waste)
668  {
669  waste = size_waste;
670  seed_1 = k;
671  seed_2 = j;
672  }
673  }
674  }
675 
676  left = v->spl_left;
677  v->spl_nleft = 0;
678  right = v->spl_right;
679  v->spl_nright = 0;
680 
681  if (seed_1 == 0 || seed_2 == 0)
682  {
683  seed_1 = 1;
684  seed_2 = 2;
685  }
686 
687  /* form initial .. */
688  datum_l = gtsvector_alloc(SIGNKEY | (cache[seed_1].allistrue ? ALLISTRUE : 0),
689  siglen, cache[seed_1].sign);
690  datum_r = gtsvector_alloc(SIGNKEY | (cache[seed_2].allistrue ? ALLISTRUE : 0),
691  siglen, cache[seed_2].sign);
692  union_l = GETSIGN(datum_l);
693  union_r = GETSIGN(datum_r);
694  maxoff = OffsetNumberNext(maxoff);
695  fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff), siglen);
696  /* sort before ... */
697  costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
698  for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
699  {
700  costvector[j - 1].pos = j;
701  size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]), siglen);
702  size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]), siglen);
703  costvector[j - 1].cost = Abs(size_alpha - size_beta);
704  }
705  qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
706 
707  for (k = 0; k < maxoff; k++)
708  {
709  j = costvector[k].pos;
710  if (j == seed_1)
711  {
712  *left++ = j;
713  v->spl_nleft++;
714  continue;
715  }
716  else if (j == seed_2)
717  {
718  *right++ = j;
719  v->spl_nright++;
720  continue;
721  }
722 
723  if (ISALLTRUE(datum_l) || cache[j].allistrue)
724  {
725  if (ISALLTRUE(datum_l) && cache[j].allistrue)
726  size_alpha = 0;
727  else
728  size_alpha = SIGLENBIT(siglen) -
729  sizebitvec((cache[j].allistrue) ?
730  GETSIGN(datum_l) :
731  GETSIGN(cache[j].sign),
732  siglen);
733  }
734  else
735  size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l), siglen);
736 
737  if (ISALLTRUE(datum_r) || cache[j].allistrue)
738  {
739  if (ISALLTRUE(datum_r) && cache[j].allistrue)
740  size_beta = 0;
741  else
742  size_beta = SIGLENBIT(siglen) -
743  sizebitvec((cache[j].allistrue) ?
744  GETSIGN(datum_r) :
745  GETSIGN(cache[j].sign),
746  siglen);
747  }
748  else
749  size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r), siglen);
750 
751  if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
752  {
753  if (ISALLTRUE(datum_l) || cache[j].allistrue)
754  {
755  if (!ISALLTRUE(datum_l))
756  MemSet((void *) GETSIGN(datum_l), 0xff, siglen);
757  }
758  else
759  {
760  ptr = cache[j].sign;
761  LOOPBYTE(siglen)
762  union_l[i] |= ptr[i];
763  }
764  *left++ = j;
765  v->spl_nleft++;
766  }
767  else
768  {
769  if (ISALLTRUE(datum_r) || cache[j].allistrue)
770  {
771  if (!ISALLTRUE(datum_r))
772  MemSet((void *) GETSIGN(datum_r), 0xff, siglen);
773  }
774  else
775  {
776  ptr = cache[j].sign;
777  LOOPBYTE(siglen)
778  union_r[i] |= ptr[i];
779  }
780  *right++ = j;
781  v->spl_nright++;
782  }
783  }
784 
785  *right = *left = FirstOffsetNumber;
786  v->spl_ldatum = PointerGetDatum(datum_l);
787  v->spl_rdatum = PointerGetDatum(datum_r);
788 
790 }
791 
792 /*
793  * Formerly, gtsvector_consistent was declared in pg_proc.h with arguments
794  * that did not match the documented conventions for GiST support functions.
795  * We fixed that, but we still need a pg_proc entry with the old signature
796  * to support reloading pre-9.6 contrib/tsearch2 opclass declarations.
797  * This compatibility function should go away eventually.
798  */
799 Datum
801 {
802  return gtsvector_consistent(fcinfo);
803 }
804 
805 Datum
807 {
809 
810  init_local_reloptions(relopts, sizeof(GistTsVectorOptions));
811  add_local_int_reloption(relopts, "siglen", "signature length",
813  offsetof(GistTsVectorOptions, siglen));
814 
815  PG_RETURN_VOID();
816 }
Relation rel
Definition: gist.h:153
static int hemdist(SignTSVector *a, SignTSVector *b)
Definition: tsgistidx.c:506
bool TS_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
Definition: tsvector_op.c:1846
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
OffsetNumber pos
Definition: hstore_gist.c:346
#define SIGLENBIT(siglen)
Definition: tsgistidx.c:40
#define INIT_LEGACY_CRC32(crc)
Definition: pg_crc.h:79
static int compareint(const void *va, const void *vb)
Definition: tsgistidx.c:127
void init_local_reloptions(local_relopts *opts, Size relopt_struct_size)
Definition: reloptions.c:710
Datum gtsvector_penalty(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:527
#define GETARR(x)
Definition: tsgistidx.c:82
static int32 sizebitvec(BITVECP sign, int siglen)
Definition: tsgistidx.c:484
Datum gtsvector_options(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:806
Datum gtsvector_same(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:423
#define ISARRKEY(x)
Definition: tsgistidx.c:73
#define VARSIZE(PTR)
Definition: postgres.h:303
static int32 unionkey(BITVECP sbase, SignTSVector *add, int siglen)
Definition: tsgistidx.c:368
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:238
static void makesign(BITVECP sign, SignTSVector *a, int siglen)
Definition: tsgistidx.c:138
OffsetNumber * spl_left
Definition: gist.h:134
Datum spl_rdatum
Definition: gist.h:141
int32 n
Definition: gist.h:227
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:283
uint32 len
Definition: ts_type.h:44
int errcode(int sqlerrcode)
Definition: elog.c:610
#define MemSet(start, val, len)
Definition: c.h:949
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define SIGLEN_DEFAULT
Definition: tsgistidx.c:34
static TSTernaryValue checkcondition_arr(void *checkval, QueryOperand *val, ExecPhraseData *data)
Definition: tsgistidx.c:279
int spl_nleft
Definition: gist.h:135
char * BITVECP
Definition: tsgistidx.c:42
static int comparecost(const void *va, const void *vb)
Definition: tsgistidx.c:589
#define LOOPBYTE(siglen)
Definition: tsgistidx.c:44
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:894
#define GETQUERY(x)
Definition: _int.h:157
#define FIN_LEGACY_CRC32(crc)
Definition: pg_crc.h:80
#define GETSIGLEN(x)
Definition: tsgistidx.c:81
signed int int32
Definition: c.h:362
uint64 pg_popcount(const char *buf, int bytes)
Definition: pg_bitutils.c:282
int32 cost
Definition: hstore_gist.c:347
uint16 OffsetNumber
Definition: off.h:24
Page page
Definition: gist.h:154
#define Abs(x)
Definition: c.h:933
static int hemdistcache(CACHESIGN *a, CACHESIGN *b, int siglen)
Definition: tsgistidx.c:602
int32 * arrb
Definition: _int_bool.c:227
#define WISH_F(a, b, c)
Definition: tsgistidx.c:581
#define sprintf
Definition: port.h:195
void pfree(void *pointer)
Definition: mcxt.c:1057
#define TOAST_INDEX_TARGET
Definition: heaptoast.h:68
#define ERROR
Definition: elog.h:43
#define CALCGTSIZE(flag, len)
Definition: tsgistidx.c:78
int spl_nright
Definition: gist.h:140
#define SIGLEN_MAX
Definition: tsgistidx.c:35
char sign
Definition: informix.c:668
Datum key
Definition: gist.h:152
char * c
#define FirstOffsetNumber
Definition: off.h:27
char * flag(int b)
Definition: test-ctype.c:33
int32 size
Definition: ts_type.h:93
int32 valcrc
Definition: ts_type.h:151
static TSTernaryValue checkcondition_bit(void *checkval, QueryOperand *val, ExecPhraseData *data)
Definition: tsgistidx.c:311
int32 flag
Definition: tsgistidx.c:65
#define GETBIT(x, i)
Definition: tsgistidx.c:51
#define ARRKEY
Definition: tsgistidx.c:69
#define GETENTRY(vec, pos)
Definition: tsgistidx.c:56
#define DatumGetTSVector(X)
Definition: ts_type.h:117
#define SINGOUTSTR
Definition: tsgistidx.c:96
bool leafkey
Definition: gist.h:156
#define ARROUTSTR
Definition: tsgistidx.c:97
Datum gtsvector_union(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:396
static void fillcache(CACHESIGN *item, SignTSVector *key, int siglen)
Definition: tsgistidx.c:570
#define HASHVAL(val, siglen)
Definition: tsgistidx.c:53
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_RETURN_VOID()
Definition: fmgr.h:348
#define EXTRALEN
Definition: tsgistidx.c:98
Datum gtsvector_consistent_oldsig(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:800
#define Max(x, y)
Definition: c.h:921
static int hemdistsign(BITVECP a, BITVECP b, int siglen)
Definition: tsgistidx.c:490
Datum spl_ldatum
Definition: gist.h:136
#define GETSIGN(x)
Definition: tsgistidx.c:80
#define Assert(condition)
Definition: c.h:745
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:236
#define TS_EXEC_PHRASE_NO_POS
Definition: ts_utils.h:198
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
#define newval
Datum gtsvector_consistent(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:328
#define ARRNELEM(x)
Definition: tsgistidx.c:83
OffsetNumber * spl_right
Definition: gist.h:139
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
Datum gtsvectorout(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:103
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
uint32 pos
Definition: ts_type.h:44
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
static SignTSVector * gtsvector_alloc(int flag, int len, BITVECP sign)
Definition: tsgistidx.c:150
#define SIGNKEY
Definition: tsgistidx.c:70
#define DatumGetPointer(X)
Definition: postgres.h:549
PGDLLIMPORT const uint8 pg_number_of_ones[256]
Definition: pg_bitutils.c:87
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
int32 * arre
Definition: _int_bool.c:228
#define STRPTR(x)
Definition: hstore.h:76
Datum gtsvector_picksplit(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:618
int32 size
Definition: ts_type.h:208
#define COMP_LEGACY_CRC32(crc, data, len)
Definition: pg_crc.h:81
int i
#define HASH(sign, val, siglen)
Definition: tsgistidx.c:54
#define ISALLTRUE(x)
Definition: tsgistidx.c:75
TSTernaryValue
Definition: ts_utils.h:128
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
bool prefix
Definition: ts_type.h:150
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
char * BITVECP
Definition: hstore_gist.c:30
uint32 pg_crc32
Definition: pg_crc.h:37
#define ARRPTR(x)
Definition: cube.c:24
bool allistrue
Definition: trgm_gist.c:735
BITVECP sign
Definition: trgm_gist.c:736
#define qsort(a, b, c, d)
Definition: port.h:475
OffsetNumber offset
Definition: gist.h:155
#define ISSIGNKEY(x)
Definition: tsgistidx.c:74
Datum gtsvector_compress(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:166
long val
Definition: informix.c:664
#define ALLISTRUE
Definition: tsgistidx.c:71
Datum gtsvector_decompress(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:246
#define GET_SIGLEN()
Definition: tsgistidx.c:36
#define offsetof(type, field)
Definition: c.h:668
static int outbuf_maxlen
Definition: tsgistidx.c:100
Datum gtsvectorin(PG_FUNCTION_ARGS)
Definition: tsgistidx.c:88
int32 vl_len_
Definition: tsgistidx.c:64