PostgreSQL Source Code  git master
to_tsany.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * to_tsany.c
4  * to_ts* function definitions
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/tsearch/to_tsany.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "common/jsonapi.h"
17 #include "tsearch/ts_cache.h"
18 #include "tsearch/ts_utils.h"
19 #include "utils/builtins.h"
20 #include "utils/jsonfuncs.h"
21 
22 
23 /*
24  * Opaque data structure, which is passed by parse_tsquery() to pushval_morph().
25  */
26 typedef struct MorphOpaque
27 {
29 
30  /*
31  * Single tsquery morph could be parsed into multiple words. When these
32  * words reside in adjacent positions, they are connected using this
33  * operator. Usually, that is OP_PHRASE, which requires word positions of
34  * a complex morph to exactly match the tsvector.
35  */
36  int qoperator;
38 
39 typedef struct TSVectorBuildState
40 {
44 
45 static void add_to_tsvector(void *_state, char *elem_value, int elem_len);
46 
47 
48 Datum
50 {
52 }
53 
54 /*
55  * to_tsvector
56  */
57 static int
58 compareWORD(const void *a, const void *b)
59 {
60  int res;
61 
62  res = tsCompareString(((const ParsedWord *) a)->word, ((const ParsedWord *) a)->len,
63  ((const ParsedWord *) b)->word, ((const ParsedWord *) b)->len,
64  false);
65 
66  if (res == 0)
67  {
68  if (((const ParsedWord *) a)->pos.pos == ((const ParsedWord *) b)->pos.pos)
69  return 0;
70 
71  res = (((const ParsedWord *) a)->pos.pos > ((const ParsedWord *) b)->pos.pos) ? 1 : -1;
72  }
73 
74  return res;
75 }
76 
77 static int
79 {
80  ParsedWord *ptr,
81  *res;
82  int tmppos;
83 
84  if (l == 1)
85  {
86  tmppos = LIMITPOS(a->pos.pos);
87  a->alen = 2;
88  a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
89  a->pos.apos[0] = 1;
90  a->pos.apos[1] = tmppos;
91  return l;
92  }
93 
94  res = a;
95  ptr = a + 1;
96 
97  /*
98  * Sort words with its positions
99  */
100  qsort(a, l, sizeof(ParsedWord), compareWORD);
101 
102  /*
103  * Initialize first word and its first position
104  */
105  tmppos = LIMITPOS(a->pos.pos);
106  a->alen = 2;
107  a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
108  a->pos.apos[0] = 1;
109  a->pos.apos[1] = tmppos;
110 
111  /*
112  * Summarize position information for each word
113  */
114  while (ptr - a < l)
115  {
116  if (!(ptr->len == res->len &&
117  strncmp(ptr->word, res->word, res->len) == 0))
118  {
119  /*
120  * Got a new word, so put it in result
121  */
122  res++;
123  res->len = ptr->len;
124  res->word = ptr->word;
125  tmppos = LIMITPOS(ptr->pos.pos);
126  res->alen = 2;
127  res->pos.apos = (uint16 *) palloc(sizeof(uint16) * res->alen);
128  res->pos.apos[0] = 1;
129  res->pos.apos[1] = tmppos;
130  }
131  else
132  {
133  /*
134  * The word already exists, so adjust position information. But
135  * before we should check size of position's array, max allowed
136  * value for position and uniqueness of position
137  */
138  pfree(ptr->word);
139  if (res->pos.apos[0] < MAXNUMPOS - 1 && res->pos.apos[res->pos.apos[0]] != MAXENTRYPOS - 1 &&
140  res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
141  {
142  if (res->pos.apos[0] + 1 >= res->alen)
143  {
144  res->alen *= 2;
145  res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
146  }
147  if (res->pos.apos[0] == 0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
148  {
149  res->pos.apos[res->pos.apos[0] + 1] = LIMITPOS(ptr->pos.pos);
150  res->pos.apos[0]++;
151  }
152  }
153  }
154  ptr++;
155  }
156 
157  return res + 1 - a;
158 }
159 
160 /*
161  * make value of tsvector, given parsed text
162  *
163  * Note: frees prs->words and subsidiary data.
164  */
165 TSVector
167 {
168  int i,
169  j,
170  lenstr = 0,
171  totallen;
172  TSVector in;
173  WordEntry *ptr;
174  char *str;
175  int stroff;
176 
177  /* Merge duplicate words */
178  if (prs->curwords > 0)
179  prs->curwords = uniqueWORD(prs->words, prs->curwords);
180 
181  /* Determine space needed */
182  for (i = 0; i < prs->curwords; i++)
183  {
184  lenstr += prs->words[i].len;
185  if (prs->words[i].alen)
186  {
187  lenstr = SHORTALIGN(lenstr);
188  lenstr += sizeof(uint16) + prs->words[i].pos.apos[0] * sizeof(WordEntryPos);
189  }
190  }
191 
192  if (lenstr > MAXSTRPOS)
193  ereport(ERROR,
194  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
195  errmsg("string is too long for tsvector (%d bytes, max %d bytes)", lenstr, MAXSTRPOS)));
196 
197  totallen = CALCDATASIZE(prs->curwords, lenstr);
198  in = (TSVector) palloc0(totallen);
199  SET_VARSIZE(in, totallen);
200  in->size = prs->curwords;
201 
202  ptr = ARRPTR(in);
203  str = STRPTR(in);
204  stroff = 0;
205  for (i = 0; i < prs->curwords; i++)
206  {
207  ptr->len = prs->words[i].len;
208  ptr->pos = stroff;
209  memcpy(str + stroff, prs->words[i].word, prs->words[i].len);
210  stroff += prs->words[i].len;
211  pfree(prs->words[i].word);
212  if (prs->words[i].alen)
213  {
214  int k = prs->words[i].pos.apos[0];
215  WordEntryPos *wptr;
216 
217  if (k > 0xFFFF)
218  elog(ERROR, "positions array too long");
219 
220  ptr->haspos = 1;
221  stroff = SHORTALIGN(stroff);
222  *(uint16 *) (str + stroff) = (uint16) k;
223  wptr = POSDATAPTR(in, ptr);
224  for (j = 0; j < k; j++)
225  {
226  WEP_SETWEIGHT(wptr[j], 0);
227  WEP_SETPOS(wptr[j], prs->words[i].pos.apos[j + 1]);
228  }
229  stroff += sizeof(uint16) + k * sizeof(WordEntryPos);
230  pfree(prs->words[i].pos.apos);
231  }
232  else
233  ptr->haspos = 0;
234  ptr++;
235  }
236 
237  if (prs->words)
238  pfree(prs->words);
239 
240  return in;
241 }
242 
243 Datum
245 {
246  Oid cfgId = PG_GETARG_OID(0);
247  text *in = PG_GETARG_TEXT_PP(1);
248  ParsedText prs;
249  TSVector out;
250 
251  prs.lenwords = VARSIZE_ANY_EXHDR(in) / 6; /* just estimation of word's
252  * number */
253  if (prs.lenwords < 2)
254  prs.lenwords = 2;
255  else if (prs.lenwords > MaxAllocSize / sizeof(ParsedWord))
256  prs.lenwords = MaxAllocSize / sizeof(ParsedWord);
257  prs.curwords = 0;
258  prs.pos = 0;
259  prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
260 
261  parsetext(cfgId, &prs, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
262 
263  PG_FREE_IF_COPY(in, 1);
264 
265  out = make_tsvector(&prs);
266 
267  PG_RETURN_TSVECTOR(out);
268 }
269 
270 Datum
272 {
273  text *in = PG_GETARG_TEXT_PP(0);
274  Oid cfgId;
275 
276  cfgId = getTSCurrentConfig(true);
278  ObjectIdGetDatum(cfgId),
279  PointerGetDatum(in)));
280 }
281 
282 /*
283  * Worker function for jsonb(_string)_to_tsvector(_byid)
284  */
285 static TSVector
287 {
289  ParsedText prs;
290 
291  prs.words = NULL;
292  prs.curwords = 0;
293  state.prs = &prs;
294  state.cfgId = cfgId;
295 
297 
298  return make_tsvector(&prs);
299 }
300 
301 Datum
303 {
304  Oid cfgId = PG_GETARG_OID(0);
305  Jsonb *jb = PG_GETARG_JSONB_P(1);
306  TSVector result;
307 
308  result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
309  PG_FREE_IF_COPY(jb, 1);
310 
311  PG_RETURN_TSVECTOR(result);
312 }
313 
314 Datum
316 {
317  Jsonb *jb = PG_GETARG_JSONB_P(0);
318  Oid cfgId;
319  TSVector result;
320 
321  cfgId = getTSCurrentConfig(true);
322  result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
323  PG_FREE_IF_COPY(jb, 0);
324 
325  PG_RETURN_TSVECTOR(result);
326 }
327 
328 Datum
330 {
331  Oid cfgId = PG_GETARG_OID(0);
332  Jsonb *jb = PG_GETARG_JSONB_P(1);
333  Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
334  TSVector result;
335  uint32 flags = parse_jsonb_index_flags(jbFlags);
336 
337  result = jsonb_to_tsvector_worker(cfgId, jb, flags);
338  PG_FREE_IF_COPY(jb, 1);
339  PG_FREE_IF_COPY(jbFlags, 2);
340 
341  PG_RETURN_TSVECTOR(result);
342 }
343 
344 Datum
346 {
347  Jsonb *jb = PG_GETARG_JSONB_P(0);
348  Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
349  Oid cfgId;
350  TSVector result;
351  uint32 flags = parse_jsonb_index_flags(jbFlags);
352 
353  cfgId = getTSCurrentConfig(true);
354  result = jsonb_to_tsvector_worker(cfgId, jb, flags);
355  PG_FREE_IF_COPY(jb, 0);
356  PG_FREE_IF_COPY(jbFlags, 1);
357 
358  PG_RETURN_TSVECTOR(result);
359 }
360 
361 /*
362  * Worker function for json(_string)_to_tsvector(_byid)
363  */
364 static TSVector
366 {
368  ParsedText prs;
369 
370  prs.words = NULL;
371  prs.curwords = 0;
372  state.prs = &prs;
373  state.cfgId = cfgId;
374 
375  iterate_json_values(json, flags, &state, add_to_tsvector);
376 
377  return make_tsvector(&prs);
378 }
379 
380 Datum
382 {
383  Oid cfgId = PG_GETARG_OID(0);
384  text *json = PG_GETARG_TEXT_P(1);
385  TSVector result;
386 
387  result = json_to_tsvector_worker(cfgId, json, jtiString);
388  PG_FREE_IF_COPY(json, 1);
389 
390  PG_RETURN_TSVECTOR(result);
391 }
392 
393 Datum
395 {
396  text *json = PG_GETARG_TEXT_P(0);
397  Oid cfgId;
398  TSVector result;
399 
400  cfgId = getTSCurrentConfig(true);
401  result = json_to_tsvector_worker(cfgId, json, jtiString);
402  PG_FREE_IF_COPY(json, 0);
403 
404  PG_RETURN_TSVECTOR(result);
405 }
406 
407 Datum
409 {
410  Oid cfgId = PG_GETARG_OID(0);
411  text *json = PG_GETARG_TEXT_P(1);
412  Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
413  TSVector result;
414  uint32 flags = parse_jsonb_index_flags(jbFlags);
415 
416  result = json_to_tsvector_worker(cfgId, json, flags);
417  PG_FREE_IF_COPY(json, 1);
418  PG_FREE_IF_COPY(jbFlags, 2);
419 
420  PG_RETURN_TSVECTOR(result);
421 }
422 
423 Datum
425 {
426  text *json = PG_GETARG_TEXT_P(0);
427  Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
428  Oid cfgId;
429  TSVector result;
430  uint32 flags = parse_jsonb_index_flags(jbFlags);
431 
432  cfgId = getTSCurrentConfig(true);
433  result = json_to_tsvector_worker(cfgId, json, flags);
434  PG_FREE_IF_COPY(json, 0);
435  PG_FREE_IF_COPY(jbFlags, 1);
436 
437  PG_RETURN_TSVECTOR(result);
438 }
439 
440 /*
441  * Parse lexemes in an element of a json(b) value, add to TSVectorBuildState.
442  */
443 static void
444 add_to_tsvector(void *_state, char *elem_value, int elem_len)
445 {
447  ParsedText *prs = state->prs;
448  int32 prevwords;
449 
450  if (prs->words == NULL)
451  {
452  /*
453  * First time through: initialize words array to a reasonable size.
454  * (parsetext() will realloc it bigger as needed.)
455  */
456  prs->lenwords = 16;
457  prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords);
458  prs->curwords = 0;
459  prs->pos = 0;
460  }
461 
462  prevwords = prs->curwords;
463 
464  parsetext(state->cfgId, prs, elem_value, elem_len);
465 
466  /*
467  * If we extracted any words from this JSON element, advance pos to create
468  * an artificial break between elements. This is because we don't want
469  * phrase searches to think that the last word in this element is adjacent
470  * to the first word in the next one.
471  */
472  if (prs->curwords > prevwords)
473  prs->pos += 1;
474 }
475 
476 
477 /*
478  * to_tsquery
479  */
480 
481 
482 /*
483  * This function is used for morph parsing.
484  *
485  * The value is passed to parsetext which will call the right dictionary to
486  * lexize the word. If it turns out to be a stopword, we push a QI_VALSTOP
487  * to the stack.
488  *
489  * All words belonging to the same variant are pushed as an ANDed list,
490  * and different variants are ORed together.
491  */
492 static void
493 pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
494 {
495  int32 count = 0;
496  ParsedText prs;
497  uint32 variant,
498  pos = 0,
499  cntvar = 0,
500  cntpos = 0,
501  cnt = 0;
503 
504  prs.lenwords = 4;
505  prs.curwords = 0;
506  prs.pos = 0;
507  prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
508 
509  parsetext(data->cfg_id, &prs, strval, lenval);
510 
511  if (prs.curwords > 0)
512  {
513  while (count < prs.curwords)
514  {
515  /*
516  * Were any stop words removed? If so, fill empty positions with
517  * placeholders linked by an appropriate operator.
518  */
519  if (pos > 0 && pos + 1 < prs.words[count].pos.pos)
520  {
521  while (pos + 1 < prs.words[count].pos.pos)
522  {
523  /* put placeholders for each missing stop word */
524  pushStop(state);
525  if (cntpos)
526  pushOperator(state, data->qoperator, 1);
527  cntpos++;
528  pos++;
529  }
530  }
531 
532  /* save current word's position */
533  pos = prs.words[count].pos.pos;
534 
535  /* Go through all variants obtained from this token */
536  cntvar = 0;
537  while (count < prs.curwords && pos == prs.words[count].pos.pos)
538  {
539  variant = prs.words[count].nvariant;
540 
541  /* Push all words belonging to the same variant */
542  cnt = 0;
543  while (count < prs.curwords &&
544  pos == prs.words[count].pos.pos &&
545  variant == prs.words[count].nvariant)
546  {
548  prs.words[count].word,
549  prs.words[count].len,
550  weight,
551  ((prs.words[count].flags & TSL_PREFIX) || prefix));
552  pfree(prs.words[count].word);
553  if (cnt)
555  cnt++;
556  count++;
557  }
558 
559  if (cntvar)
560  pushOperator(state, OP_OR, 0);
561  cntvar++;
562  }
563 
564  if (cntpos)
565  {
566  /* distance may be useful */
567  pushOperator(state, data->qoperator, 1);
568  }
569 
570  cntpos++;
571  }
572 
573  pfree(prs.words);
574  }
575  else
576  pushStop(state);
577 }
578 
579 Datum
581 {
582  text *in = PG_GETARG_TEXT_PP(1);
583  TSQuery query;
585 
586  data.cfg_id = PG_GETARG_OID(0);
587 
588  /*
589  * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
590  * positions of a complex morph exactly match the tsvector. Also, when
591  * the complex morphs are connected with OP_PHRASE operator, we connect
592  * all their words into the OP_PHRASE sequence.
593  */
594  data.qoperator = OP_PHRASE;
595 
596  query = parse_tsquery(text_to_cstring(in),
599  0,
600  NULL);
601 
602  PG_RETURN_TSQUERY(query);
603 }
604 
605 Datum
607 {
608  text *in = PG_GETARG_TEXT_PP(0);
609  Oid cfgId;
610 
611  cfgId = getTSCurrentConfig(true);
613  ObjectIdGetDatum(cfgId),
614  PointerGetDatum(in)));
615 }
616 
617 Datum
619 {
620  text *in = PG_GETARG_TEXT_PP(1);
621  TSQuery query;
623 
624  data.cfg_id = PG_GETARG_OID(0);
625 
626  /*
627  * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
628  * single morph. Passing OP_PHRASE as a qoperator makes tsquery require
629  * matching of all words independently on their positions.
630  */
631  data.qoperator = OP_AND;
632 
633  query = parse_tsquery(text_to_cstring(in),
636  P_TSQ_PLAIN,
637  NULL);
638 
639  PG_RETURN_POINTER(query);
640 }
641 
642 Datum
644 {
645  text *in = PG_GETARG_TEXT_PP(0);
646  Oid cfgId;
647 
648  cfgId = getTSCurrentConfig(true);
650  ObjectIdGetDatum(cfgId),
651  PointerGetDatum(in)));
652 }
653 
654 
655 Datum
657 {
658  text *in = PG_GETARG_TEXT_PP(1);
659  TSQuery query;
661 
662  data.cfg_id = PG_GETARG_OID(0);
663 
664  /*
665  * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
666  * single morph. Passing OP_PHRASE as a qoperator makes tsquery require
667  * matching of word positions.
668  */
669  data.qoperator = OP_PHRASE;
670 
671  query = parse_tsquery(text_to_cstring(in),
674  P_TSQ_PLAIN,
675  NULL);
676 
677  PG_RETURN_TSQUERY(query);
678 }
679 
680 Datum
682 {
683  text *in = PG_GETARG_TEXT_PP(0);
684  Oid cfgId;
685 
686  cfgId = getTSCurrentConfig(true);
688  ObjectIdGetDatum(cfgId),
689  PointerGetDatum(in)));
690 }
691 
692 Datum
694 {
695  text *in = PG_GETARG_TEXT_PP(1);
697  TSQuery query = NULL;
698 
699  data.cfg_id = PG_GETARG_OID(0);
700 
701  /*
702  * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
703  * positions of a complex morph exactly match the tsvector. Also, when
704  * the complex morphs are given in quotes, we connect all their words into
705  * the OP_PHRASE sequence.
706  */
707  data.qoperator = OP_PHRASE;
708 
709  query = parse_tsquery(text_to_cstring(in),
712  P_TSQ_WEB,
713  NULL);
714 
715  PG_RETURN_TSQUERY(query);
716 }
717 
718 Datum
720 {
721  text *in = PG_GETARG_TEXT_PP(0);
722  Oid cfgId;
723 
724  cfgId = getTSCurrentConfig(true);
726  ObjectIdGetDatum(cfgId),
727  PointerGetDatum(in)));
728 }
unsigned short uint16
Definition: c.h:494
unsigned int uint32
Definition: c.h:495
signed short int16
Definition: c.h:482
signed int int32
Definition: c.h:483
#define SHORTALIGN(LEN)
Definition: c.h:796
#define ARRPTR(x)
Definition: cube.c:25
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:336
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define STRPTR(x)
Definition: hstore.h:76
int b
Definition: isn.c:70
int a
Definition: isn.c:69
int j
Definition: isn.c:74
int i
Definition: isn.c:73
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
uint32 parse_jsonb_index_flags(Jsonb *jb)
Definition: jsonfuncs.c:5297
void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
Definition: jsonfuncs.c:5365
void iterate_json_values(text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
Definition: jsonfuncs.c:5433
@ jtiString
Definition: jsonfuncs.h:27
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * palloc(Size size)
Definition: mcxt.c:1226
#define MaxAllocSize
Definition: memutils.h:40
const void size_t len
const void * data
#define qsort(a, b, c, d)
Definition: port.h:445
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
unsigned int Oid
Definition: postgres_ext.h:31
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition: regcomp.c:1474
Definition: jsonb.h:213
int qoperator
Definition: to_tsany.c:36
Oid cfg_id
Definition: to_tsany.c:28
int32 pos
Definition: ts_utils.h:107
int32 lenwords
Definition: ts_utils.h:105
int32 curwords
Definition: ts_utils.h:106
ParsedWord * words
Definition: ts_utils.h:104
uint16 alen
Definition: ts_utils.h:87
uint16 flags
Definition: ts_utils.h:84
uint16 nvariant
Definition: ts_utils.h:86
uint16 len
Definition: ts_utils.h:85
uint16 pos
Definition: ts_utils.h:90
char * word
Definition: ts_utils.h:99
ParsedText * prs
Definition: to_tsany.c:41
int32 size
Definition: ts_type.h:93
uint32 pos
Definition: ts_type.h:46
uint32 haspos
Definition: ts_type.h:44
uint32 len
Definition: ts_type.h:45
Definition: regguts.h:323
Definition: c.h:676
static TSVector json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
Definition: to_tsany.c:365
static void add_to_tsvector(void *_state, char *elem_value, int elem_len)
Definition: to_tsany.c:444
Datum phraseto_tsquery(PG_FUNCTION_ARGS)
Definition: to_tsany.c:681
Datum to_tsvector(PG_FUNCTION_ARGS)
Definition: to_tsany.c:271
static int compareWORD(const void *a, const void *b)
Definition: to_tsany.c:58
Datum plainto_tsquery_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:618
struct TSVectorBuildState TSVectorBuildState
Datum to_tsquery(PG_FUNCTION_ARGS)
Definition: to_tsany.c:606
static TSVector jsonb_to_tsvector_worker(Oid cfgId, Jsonb *jb, uint32 flags)
Definition: to_tsany.c:286
Datum json_string_to_tsvector(PG_FUNCTION_ARGS)
Definition: to_tsany.c:394
Datum jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:329
Datum json_to_tsvector(PG_FUNCTION_ARGS)
Definition: to_tsany.c:424
Datum json_to_tsvector_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:408
Datum jsonb_string_to_tsvector_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:302
Datum phraseto_tsquery_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:656
Datum to_tsvector_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:244
struct MorphOpaque MorphOpaque
Datum jsonb_to_tsvector(PG_FUNCTION_ARGS)
Definition: to_tsany.c:345
TSVector make_tsvector(ParsedText *prs)
Definition: to_tsany.c:166
static void pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
Definition: to_tsany.c:493
Datum get_current_ts_config(PG_FUNCTION_ARGS)
Definition: to_tsany.c:49
Datum websearch_to_tsquery(PG_FUNCTION_ARGS)
Definition: to_tsany.c:719
Datum to_tsquery_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:580
Datum json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:381
Datum jsonb_string_to_tsvector(PG_FUNCTION_ARGS)
Definition: to_tsany.c:315
static int uniqueWORD(ParsedWord *a, int32 l)
Definition: to_tsany.c:78
Datum websearch_to_tsquery_byid(PG_FUNCTION_ARGS)
Definition: to_tsany.c:693
Datum plainto_tsquery(PG_FUNCTION_ARGS)
Definition: to_tsany.c:643
Oid getTSCurrentConfig(bool emitError)
Definition: ts_cache.c:556
void parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen)
Definition: ts_parse.c:355
#define TSL_PREFIX
Definition: ts_public.h:143
#define PG_RETURN_TSVECTOR(x)
Definition: ts_type.h:137
#define MAXENTRYPOS
Definition: ts_type.h:85
#define WEP_SETPOS(x, v)
Definition: ts_type.h:83
uint16 WordEntryPos
Definition: ts_type.h:63
#define PG_RETURN_TSQUERY(x)
Definition: ts_type.h:268
#define MAXNUMPOS
Definition: ts_type.h:86
TSVectorData * TSVector
Definition: ts_type.h:98
#define WEP_SETWEIGHT(x, v)
Definition: ts_type.h:82
#define LIMITPOS(x)
Definition: ts_type.h:87
#define OP_AND
Definition: ts_type.h:180
#define OP_PHRASE
Definition: ts_type.h:182
#define OP_OR
Definition: ts_type.h:181
#define POSDATAPTR(x, e)
Definition: ts_type.h:111
#define MAXSTRPOS
Definition: ts_type.h:50
#define P_TSQ_PLAIN
Definition: ts_utils.h:64
#define P_TSQ_WEB
Definition: ts_utils.h:65
void pushValue(TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
Definition: tsquery.c:584
TSQuery parse_tsquery(char *buf, PushFunction pushval, Datum opaque, int flags, Node *escontext)
Definition: tsquery.c:821
void pushOperator(TSQueryParserState state, int8 oper, int16 distance)
Definition: tsquery.c:535
void pushStop(TSQueryParserState state)
Definition: tsquery.c:620
int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
Definition: tsvector_op.c:1154
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
char * text_to_cstring(const text *t)
Definition: varlena.c:215