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