PostgreSQL Source Code  git master
ts_utils.h File Reference
#include "nodes/pg_list.h"
#include "tsearch/ts_public.h"
#include "tsearch/ts_type.h"
Include dependency graph for ts_utils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ParsedWord
 
struct  ParsedText
 
struct  ExecPhraseData
 
struct  QTNode
 

Macros

#define P_TSV_OPR_IS_DELIM   (1 << 0)
 
#define P_TSV_IS_TSQUERY   (1 << 1)
 
#define P_TSV_IS_WEB   (1 << 2)
 
#define ISOPERATOR(x)
 
#define P_TSQ_PLAIN   (1 << 0)
 
#define P_TSQ_WEB   (1 << 1)
 
#define TS_EXEC_EMPTY   (0x00)
 
#define TS_EXEC_SKIP_NOT   (0x01)
 
#define TS_EXEC_PHRASE_NO_POS   (0x02)
 
#define TSearchStrategyNumber   1
 
#define TSearchWithClassStrategyNumber   2
 
#define QTN_NEEDFREE   0x01
 
#define QTN_NOCHANGE   0x02
 
#define QTN_WORDFREE   0x04
 
#define TSQS_SIGLEN   (sizeof(TSQuerySign)*BITS_PER_BYTE)
 
#define PG_RETURN_TSQUERYSIGN(X)   return TSQuerySignGetDatum(X)
 
#define PG_GETARG_TSQUERYSIGN(n)   DatumGetTSQuerySign(PG_GETARG_DATUM(n))
 

Typedefs

typedef struct TSVectorParseStateDataTSVectorParseState
 
typedef struct TSQueryParserStateDataTSQueryParserState
 
typedef void(* PushFunction) (Datum opaque, TSQueryParserState state, char *token, int tokenlen, int16 tokenweights, bool prefix)
 
typedef struct ExecPhraseData ExecPhraseData
 
typedef TSTernaryValue(* TSExecuteCallback) (void *arg, QueryOperand *val, ExecPhraseData *data)
 
typedef struct QTNode QTNode
 
typedef uint64 TSQuerySign
 

Enumerations

enum  TSTernaryValue { TS_NO , TS_YES , TS_MAYBE }
 

Functions

TSVectorParseState init_tsvector_parser (char *input, int flags, Node *escontext)
 
void reset_tsvector_parser (TSVectorParseState state, char *input)
 
bool gettoken_tsvector (TSVectorParseState state, char **strval, int *lenval, WordEntryPos **pos_ptr, int *poslen, char **endptr)
 
void close_tsvector_parser (TSVectorParseState state)
 
TSQuery parse_tsquery (char *buf, PushFunction pushval, Datum opaque, int flags, Node *escontext)
 
void pushValue (TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
 
void pushStop (TSQueryParserState state)
 
void pushOperator (TSQueryParserState state, int8 oper, int16 distance)
 
void parsetext (Oid cfgId, ParsedText *prs, char *buf, int32 buflen)
 
void hlparsetext (Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int32 buflen)
 
textgenerateHeadline (HeadlineParsedText *prs)
 
bool TS_execute (QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
 
TSTernaryValue TS_execute_ternary (QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
 
ListTS_execute_locations (QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
 
bool tsquery_requires_match (QueryItem *curitem)
 
TSVector make_tsvector (ParsedText *prs)
 
int32 tsCompareString (char *a, int lena, char *b, int lenb, bool prefix)
 
QueryItemclean_NOT (QueryItem *ptr, int32 *len)
 
TSQuery cleanup_tsquery_stopwords (TSQuery in, bool noisy)
 
static Datum TSQuerySignGetDatum (TSQuerySign X)
 
static TSQuerySign DatumGetTSQuerySign (Datum X)
 
QTNodeQT2QTN (QueryItem *in, char *operand)
 
TSQuery QTN2QT (QTNode *in)
 
void QTNFree (QTNode *in)
 
void QTNSort (QTNode *in)
 
void QTNTernary (QTNode *in)
 
void QTNBinary (QTNode *in)
 
int QTNodeCompare (QTNode *an, QTNode *bn)
 
QTNodeQTNCopy (QTNode *in)
 
void QTNClearFlags (QTNode *in, uint32 flags)
 
bool QTNEq (QTNode *a, QTNode *b)
 
TSQuerySign makeTSQuerySign (TSQuery a)
 
QTNodefindsubquery (QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)
 

Macro Definition Documentation

◆ ISOPERATOR

#define ISOPERATOR (   x)
Value:
( pg_mblen(x) == 1 && ( *(x) == '!' || \
*(x) == '&' || \
*(x) == '|' || \
*(x) == '(' || \
*(x) == ')' || \
*(x) == '<' \
) )
int x
Definition: isn.c:71
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023

Definition at line 43 of file ts_utils.h.

◆ P_TSQ_PLAIN

#define P_TSQ_PLAIN   (1 << 0)

Definition at line 64 of file ts_utils.h.

◆ P_TSQ_WEB

#define P_TSQ_WEB   (1 << 1)

Definition at line 65 of file ts_utils.h.

◆ P_TSV_IS_TSQUERY

#define P_TSV_IS_TSQUERY   (1 << 1)

Definition at line 30 of file ts_utils.h.

◆ P_TSV_IS_WEB

#define P_TSV_IS_WEB   (1 << 2)

Definition at line 31 of file ts_utils.h.

◆ P_TSV_OPR_IS_DELIM

#define P_TSV_OPR_IS_DELIM   (1 << 0)

Definition at line 29 of file ts_utils.h.

◆ PG_GETARG_TSQUERYSIGN

#define PG_GETARG_TSQUERYSIGN (   n)    DatumGetTSQuerySign(PG_GETARG_DATUM(n))

Definition at line 266 of file ts_utils.h.

◆ PG_RETURN_TSQUERYSIGN

#define PG_RETURN_TSQUERYSIGN (   X)    return TSQuerySignGetDatum(X)

Definition at line 265 of file ts_utils.h.

◆ QTN_NEEDFREE

#define QTN_NEEDFREE   0x01

Definition at line 245 of file ts_utils.h.

◆ QTN_NOCHANGE

#define QTN_NOCHANGE   0x02

Definition at line 246 of file ts_utils.h.

◆ QTN_WORDFREE

#define QTN_WORDFREE   0x04

Definition at line 247 of file ts_utils.h.

◆ TS_EXEC_EMPTY

#define TS_EXEC_EMPTY   (0x00)

Definition at line 188 of file ts_utils.h.

◆ TS_EXEC_PHRASE_NO_POS

#define TS_EXEC_PHRASE_NO_POS   (0x02)

Definition at line 202 of file ts_utils.h.

◆ TS_EXEC_SKIP_NOT

#define TS_EXEC_SKIP_NOT   (0x01)

Definition at line 195 of file ts_utils.h.

◆ TSearchStrategyNumber

#define TSearchStrategyNumber   1

Definition at line 225 of file ts_utils.h.

◆ TSearchWithClassStrategyNumber

#define TSearchWithClassStrategyNumber   2

Definition at line 226 of file ts_utils.h.

◆ TSQS_SIGLEN

#define TSQS_SIGLEN   (sizeof(TSQuerySign)*BITS_PER_BYTE)

Definition at line 251 of file ts_utils.h.

Typedef Documentation

◆ ExecPhraseData

◆ PushFunction

typedef void(* PushFunction) (Datum opaque, TSQueryParserState state, char *token, int tokenlen, int16 tokenweights, bool prefix)

Definition at line 57 of file ts_utils.h.

◆ QTNode

typedef struct QTNode QTNode

◆ TSExecuteCallback

typedef TSTernaryValue(* TSExecuteCallback) (void *arg, QueryOperand *val, ExecPhraseData *data)

Definition at line 182 of file ts_utils.h.

◆ TSQueryParserState

Definition at line 55 of file ts_utils.h.

◆ TSQuerySign

typedef uint64 TSQuerySign

Definition at line 249 of file ts_utils.h.

◆ TSVectorParseState

Definition at line 26 of file ts_utils.h.

Enumeration Type Documentation

◆ TSTernaryValue

Enumerator
TS_NO 
TS_YES 
TS_MAYBE 

Definition at line 132 of file ts_utils.h.

133 {
134  TS_NO, /* definitely no match */
135  TS_YES, /* definitely does match */
136  TS_MAYBE, /* can't verify match for lack of pos data */
TSTernaryValue
Definition: ts_utils.h:133
@ TS_MAYBE
Definition: ts_utils.h:136
@ TS_NO
Definition: ts_utils.h:134
@ TS_YES
Definition: ts_utils.h:135

Function Documentation

◆ clean_NOT()

QueryItem* clean_NOT ( QueryItem ptr,
int32 len 
)

◆ cleanup_tsquery_stopwords()

TSQuery cleanup_tsquery_stopwords ( TSQuery  in,
bool  noisy 
)

Definition at line 387 of file tsquery_cleanup.c.

388 {
389  int32 len,
390  lenstr,
391  commonlen,
392  i;
393  NODE *root;
394  int ladd,
395  radd;
396  TSQuery out;
397  QueryItem *items;
398  char *operands;
399 
400  if (in->size == 0)
401  return in;
402 
403  /* eliminate stop words */
404  root = clean_stopword_intree(maketree(GETQUERY(in)), &ladd, &radd);
405  if (root == NULL)
406  {
407  if (noisy)
408  ereport(NOTICE,
409  (errmsg("text-search query contains only stop words or doesn't contain lexemes, ignored")));
410  out = palloc(HDRSIZETQ);
411  out->size = 0;
412  SET_VARSIZE(out, HDRSIZETQ);
413  return out;
414  }
415 
416  /*
417  * Build TSQuery from plain view
418  */
419 
420  lenstr = calcstrlen(root);
421  items = plaintree(root, &len);
422  commonlen = COMPUTESIZE(len, lenstr);
423 
424  out = palloc(commonlen);
425  SET_VARSIZE(out, commonlen);
426  out->size = len;
427 
428  memcpy(GETQUERY(out), items, len * sizeof(QueryItem));
429 
430  items = GETQUERY(out);
431  operands = GETOPERAND(out);
432  for (i = 0; i < out->size; i++)
433  {
434  QueryOperand *op = (QueryOperand *) &items[i];
435 
436  if (op->type != QI_VAL)
437  continue;
438 
439  memcpy(operands, GETOPERAND(in) + op->distance, op->length);
440  operands[op->length] = '\0';
441  op->distance = operands - GETOPERAND(out);
442  operands += op->length + 1;
443  }
444 
445  return out;
446 }
#define COMPUTESIZE(size)
Definition: _int.h:155
#define GETQUERY(x)
Definition: _int.h:157
signed int int32
Definition: c.h:494
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
int i
Definition: isn.c:73
#define GETOPERAND(x)
Definition: ltree.h:165
void * palloc(Size size)
Definition: mcxt.c:1316
const void size_t len
tree ctl root
Definition: radixtree.h:1884
Definition: _int_bool.c:27
QueryItemType type
Definition: ts_type.h:158
uint32 distance
Definition: ts_type.h:172
uint32 length
Definition: ts_type.h:171
int32 size
Definition: ts_type.h:221
static ItemArray items
Definition: test_tidstore.c:49
#define HDRSIZETQ
Definition: ts_type.h:227
#define QI_VAL
Definition: ts_type.h:149
static NODE * clean_stopword_intree(NODE *node, int *ladd, int *radd)
static NODE * maketree(QueryItem *in)
static QueryItem * plaintree(NODE *root, int *len)
static int32 calcstrlen(NODE *node)
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References calcstrlen(), clean_stopword_intree(), COMPUTESIZE, QueryOperand::distance, ereport, errmsg(), GETOPERAND, GETQUERY, HDRSIZETQ, i, items, len, QueryOperand::length, maketree(), NOTICE, palloc(), plaintree(), QI_VAL, root, SET_VARSIZE, TSQueryData::size, and QueryOperand::type.

Referenced by parse_tsquery().

◆ close_tsvector_parser()

void close_tsvector_parser ( TSVectorParseState  state)

Definition at line 90 of file tsvector_parser.c.

91 {
92  pfree(state->word);
93  pfree(state);
94 }
void pfree(void *pointer)
Definition: mcxt.c:1520
Definition: regguts.h:323

References pfree().

Referenced by parse_tsquery(), and tsvectorin().

◆ DatumGetTSQuerySign()

static TSQuerySign DatumGetTSQuerySign ( Datum  X)
inlinestatic

Definition at line 260 of file ts_utils.h.

261 {
262  return (TSQuerySign) DatumGetInt64(X);
263 }
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
uint64 TSQuerySign
Definition: ts_utils.h:249

References DatumGetInt64().

Referenced by gtsquery_consistent(), and gtsquery_penalty().

◆ findsubquery()

QTNode* findsubquery ( QTNode root,
QTNode ex,
QTNode subs,
bool isfind 
)

Definition at line 267 of file tsquery_rewrite.c.

268 {
269  bool DidFind = false;
270 
271  root = dofindsubquery(root, ex, subs, &DidFind);
272 
273  if (isfind)
274  *isfind = DidFind;
275 
276  return root;
277 }
static QTNode * dofindsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)

References dofindsubquery(), and root.

Referenced by tsquery_rewrite(), and tsquery_rewrite_query().

◆ generateHeadline()

text* generateHeadline ( HeadlineParsedText prs)

Definition at line 607 of file ts_parse.c.

608 {
609  text *out;
610  char *ptr;
611  int len = 128;
612  int numfragments = 0;
613  int16 infrag = 0;
614 
615  HeadlineWordEntry *wrd = prs->words;
616 
617  out = (text *) palloc(len);
618  ptr = ((char *) out) + VARHDRSZ;
619 
620  while (wrd - prs->words < prs->curwords)
621  {
622  while (wrd->len + prs->stopsellen + prs->startsellen + prs->fragdelimlen + (ptr - ((char *) out)) >= len)
623  {
624  int dist = ptr - ((char *) out);
625 
626  len *= 2;
627  out = (text *) repalloc(out, len);
628  ptr = ((char *) out) + dist;
629  }
630 
631  if (wrd->in && !wrd->repeated)
632  {
633  if (!infrag)
634  {
635 
636  /* start of a new fragment */
637  infrag = 1;
638  numfragments++;
639  /* add a fragment delimiter if this is after the first one */
640  if (numfragments > 1)
641  {
642  memcpy(ptr, prs->fragdelim, prs->fragdelimlen);
643  ptr += prs->fragdelimlen;
644  }
645  }
646  if (wrd->replace)
647  {
648  *ptr = ' ';
649  ptr++;
650  }
651  else if (!wrd->skip)
652  {
653  if (wrd->selected)
654  {
655  memcpy(ptr, prs->startsel, prs->startsellen);
656  ptr += prs->startsellen;
657  }
658  memcpy(ptr, wrd->word, wrd->len);
659  ptr += wrd->len;
660  if (wrd->selected)
661  {
662  memcpy(ptr, prs->stopsel, prs->stopsellen);
663  ptr += prs->stopsellen;
664  }
665  }
666  }
667  else if (!wrd->repeated)
668  {
669  if (infrag)
670  infrag = 0;
671  pfree(wrd->word);
672  }
673 
674  wrd++;
675  }
676 
677  SET_VARSIZE(out, ptr - ((char *) out));
678  return out;
679 }
signed short int16
Definition: c.h:493
#define VARHDRSZ
Definition: c.h:692
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
HeadlineWordEntry * words
Definition: ts_public.h:76
Definition: c.h:687

References HeadlineParsedText::curwords, HeadlineParsedText::fragdelim, HeadlineParsedText::fragdelimlen, HeadlineWordEntry::in, HeadlineWordEntry::len, len, palloc(), pfree(), repalloc(), HeadlineWordEntry::repeated, HeadlineWordEntry::replace, HeadlineWordEntry::selected, SET_VARSIZE, HeadlineWordEntry::skip, HeadlineParsedText::startsel, HeadlineParsedText::startsellen, HeadlineParsedText::stopsel, HeadlineParsedText::stopsellen, VARHDRSZ, HeadlineWordEntry::word, and HeadlineParsedText::words.

Referenced by headline_json_value(), and ts_headline_byid_opt().

◆ gettoken_tsvector()

bool gettoken_tsvector ( TSVectorParseState  state,
char **  strval,
int *  lenval,
WordEntryPos **  pos_ptr,
int *  poslen,
char **  endptr 
)

Definition at line 176 of file tsvector_parser.c.

180 {
181  int oldstate = 0;
182  char *curpos = state->word;
183  int statecode = WAITWORD;
184 
185  /*
186  * pos is for collecting the comma delimited list of positions followed by
187  * the actual token.
188  */
189  WordEntryPos *pos = NULL;
190  int npos = 0; /* elements of pos used */
191  int posalen = 0; /* allocated size of pos */
192 
193  while (1)
194  {
195  if (statecode == WAITWORD)
196  {
197  if (*(state->prsbuf) == '\0')
198  return false;
199  else if (!state->is_web && t_iseq(state->prsbuf, '\''))
200  statecode = WAITENDCMPLX;
201  else if (!state->is_web && t_iseq(state->prsbuf, '\\'))
202  {
203  statecode = WAITNEXTCHAR;
204  oldstate = WAITENDWORD;
205  }
206  else if ((state->oprisdelim && ISOPERATOR(state->prsbuf)) ||
207  (state->is_web && t_iseq(state->prsbuf, '"')))
209  else if (!t_isspace(state->prsbuf))
210  {
211  COPYCHAR(curpos, state->prsbuf);
212  curpos += pg_mblen(state->prsbuf);
213  statecode = WAITENDWORD;
214  }
215  }
216  else if (statecode == WAITNEXTCHAR)
217  {
218  if (*(state->prsbuf) == '\0')
219  ereturn(state->escontext, false,
220  (errcode(ERRCODE_SYNTAX_ERROR),
221  errmsg("there is no escaped character: \"%s\"",
222  state->bufstart)));
223  else
224  {
225  RESIZEPRSBUF;
226  COPYCHAR(curpos, state->prsbuf);
227  curpos += pg_mblen(state->prsbuf);
228  Assert(oldstate != 0);
229  statecode = oldstate;
230  }
231  }
232  else if (statecode == WAITENDWORD)
233  {
234  if (!state->is_web && t_iseq(state->prsbuf, '\\'))
235  {
236  statecode = WAITNEXTCHAR;
237  oldstate = WAITENDWORD;
238  }
239  else if (t_isspace(state->prsbuf) || *(state->prsbuf) == '\0' ||
240  (state->oprisdelim && ISOPERATOR(state->prsbuf)) ||
241  (state->is_web && t_iseq(state->prsbuf, '"')))
242  {
243  RESIZEPRSBUF;
244  if (curpos == state->word)
246  *(curpos) = '\0';
247  RETURN_TOKEN;
248  }
249  else if (t_iseq(state->prsbuf, ':'))
250  {
251  if (curpos == state->word)
253  *(curpos) = '\0';
254  if (state->oprisdelim)
255  RETURN_TOKEN;
256  else
257  statecode = INPOSINFO;
258  }
259  else
260  {
261  RESIZEPRSBUF;
262  COPYCHAR(curpos, state->prsbuf);
263  curpos += pg_mblen(state->prsbuf);
264  }
265  }
266  else if (statecode == WAITENDCMPLX)
267  {
268  if (!state->is_web && t_iseq(state->prsbuf, '\''))
269  {
270  statecode = WAITCHARCMPLX;
271  }
272  else if (!state->is_web && t_iseq(state->prsbuf, '\\'))
273  {
274  statecode = WAITNEXTCHAR;
275  oldstate = WAITENDCMPLX;
276  }
277  else if (*(state->prsbuf) == '\0')
279  else
280  {
281  RESIZEPRSBUF;
282  COPYCHAR(curpos, state->prsbuf);
283  curpos += pg_mblen(state->prsbuf);
284  }
285  }
286  else if (statecode == WAITCHARCMPLX)
287  {
288  if (!state->is_web && t_iseq(state->prsbuf, '\''))
289  {
290  RESIZEPRSBUF;
291  COPYCHAR(curpos, state->prsbuf);
292  curpos += pg_mblen(state->prsbuf);
293  statecode = WAITENDCMPLX;
294  }
295  else
296  {
297  RESIZEPRSBUF;
298  *(curpos) = '\0';
299  if (curpos == state->word)
301  if (state->oprisdelim)
302  {
303  /* state->prsbuf+=pg_mblen(state->prsbuf); */
304  RETURN_TOKEN;
305  }
306  else
307  statecode = WAITPOSINFO;
308  continue; /* recheck current character */
309  }
310  }
311  else if (statecode == WAITPOSINFO)
312  {
313  if (t_iseq(state->prsbuf, ':'))
314  statecode = INPOSINFO;
315  else
316  RETURN_TOKEN;
317  }
318  else if (statecode == INPOSINFO)
319  {
320  if (t_isdigit(state->prsbuf))
321  {
322  if (posalen == 0)
323  {
324  posalen = 4;
325  pos = (WordEntryPos *) palloc(sizeof(WordEntryPos) * posalen);
326  npos = 0;
327  }
328  else if (npos + 1 >= posalen)
329  {
330  posalen *= 2;
331  pos = (WordEntryPos *) repalloc(pos, sizeof(WordEntryPos) * posalen);
332  }
333  npos++;
334  WEP_SETPOS(pos[npos - 1], LIMITPOS(atoi(state->prsbuf)));
335  /* we cannot get here in tsquery, so no need for 2 errmsgs */
336  if (WEP_GETPOS(pos[npos - 1]) == 0)
337  ereturn(state->escontext, false,
338  (errcode(ERRCODE_SYNTAX_ERROR),
339  errmsg("wrong position info in tsvector: \"%s\"",
340  state->bufstart)));
341  WEP_SETWEIGHT(pos[npos - 1], 0);
342  statecode = WAITPOSDELIM;
343  }
344  else
346  }
347  else if (statecode == WAITPOSDELIM)
348  {
349  if (t_iseq(state->prsbuf, ','))
350  statecode = INPOSINFO;
351  else if (t_iseq(state->prsbuf, 'a') || t_iseq(state->prsbuf, 'A') || t_iseq(state->prsbuf, '*'))
352  {
353  if (WEP_GETWEIGHT(pos[npos - 1]))
355  WEP_SETWEIGHT(pos[npos - 1], 3);
356  }
357  else if (t_iseq(state->prsbuf, 'b') || t_iseq(state->prsbuf, 'B'))
358  {
359  if (WEP_GETWEIGHT(pos[npos - 1]))
361  WEP_SETWEIGHT(pos[npos - 1], 2);
362  }
363  else if (t_iseq(state->prsbuf, 'c') || t_iseq(state->prsbuf, 'C'))
364  {
365  if (WEP_GETWEIGHT(pos[npos - 1]))
367  WEP_SETWEIGHT(pos[npos - 1], 1);
368  }
369  else if (t_iseq(state->prsbuf, 'd') || t_iseq(state->prsbuf, 'D'))
370  {
371  if (WEP_GETWEIGHT(pos[npos - 1]))
373  WEP_SETWEIGHT(pos[npos - 1], 0);
374  }
375  else if (t_isspace(state->prsbuf) ||
376  *(state->prsbuf) == '\0')
377  RETURN_TOKEN;
378  else if (!t_isdigit(state->prsbuf))
380  }
381  else /* internal error */
382  elog(ERROR, "unrecognized state in gettoken_tsvector: %d",
383  statecode);
384 
385  /* get next char */
386  state->prsbuf += pg_mblen(state->prsbuf);
387  }
388 }
#define Assert(condition)
Definition: c.h:858
int errcode(int sqlerrcode)
Definition: elog.c:859
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ISOPERATOR(x)
Definition: ltree.h:167
int t_isspace(const char *ptr)
Definition: ts_locale.c:50
int t_isdigit(const char *ptr)
Definition: ts_locale.c:35
#define t_iseq(x, c)
Definition: ts_locale.h:38
#define COPYCHAR(d, s)
Definition: ts_locale.h:40
#define WEP_GETPOS(x)
Definition: ts_type.h:80
#define WEP_SETPOS(x, v)
Definition: ts_type.h:83
uint16 WordEntryPos
Definition: ts_type.h:63
#define WEP_SETWEIGHT(x, v)
Definition: ts_type.h:82
#define LIMITPOS(x)
Definition: ts_type.h:87
#define WEP_GETWEIGHT(x)
Definition: ts_type.h:79
#define WAITNEXTCHAR
#define PRSSYNTAXERROR
#define WAITENDCMPLX
#define WAITENDWORD
#define WAITCHARCMPLX
#define WAITPOSINFO
#define WAITWORD
#define INPOSINFO
#define RESIZEPRSBUF
#define RETURN_TOKEN
#define WAITPOSDELIM

References Assert, COPYCHAR, elog, ereturn, errcode(), errmsg(), ERROR, INPOSINFO, ISOPERATOR, LIMITPOS, palloc(), pg_mblen(), PRSSYNTAXERROR, repalloc(), RESIZEPRSBUF, RETURN_TOKEN, t_isdigit(), t_iseq, t_isspace(), WAITCHARCMPLX, WAITENDCMPLX, WAITENDWORD, WAITNEXTCHAR, WAITPOSDELIM, WAITPOSINFO, WAITWORD, WEP_GETPOS, WEP_GETWEIGHT, WEP_SETPOS, and WEP_SETWEIGHT.

Referenced by gettoken_query_standard(), gettoken_query_websearch(), and tsvectorin().

◆ hlparsetext()

void hlparsetext ( Oid  cfgId,
HeadlineParsedText prs,
TSQuery  query,
char *  buf,
int32  buflen 
)

◆ init_tsvector_parser()

TSVectorParseState init_tsvector_parser ( char *  input,
int  flags,
Node escontext 
)

Definition at line 57 of file tsvector_parser.c.

58 {
60 
62  state->prsbuf = input;
63  state->bufstart = input;
64  state->len = 32;
65  state->word = (char *) palloc(state->len);
67  state->oprisdelim = (flags & P_TSV_OPR_IS_DELIM) != 0;
68  state->is_tsquery = (flags & P_TSV_IS_TSQUERY) != 0;
69  state->is_web = (flags & P_TSV_IS_WEB) != 0;
70  state->escontext = escontext;
71 
72  return state;
73 }
FILE * input
int pg_database_encoding_max_length(void)
Definition: mbutils.c:1546
#define P_TSV_IS_TSQUERY
Definition: ts_utils.h:30
struct TSVectorParseStateData * TSVectorParseState
Definition: ts_utils.h:26
#define P_TSV_IS_WEB
Definition: ts_utils.h:31
#define P_TSV_OPR_IS_DELIM
Definition: ts_utils.h:29

References input, P_TSV_IS_TSQUERY, P_TSV_IS_WEB, P_TSV_OPR_IS_DELIM, palloc(), and pg_database_encoding_max_length().

Referenced by parse_tsquery(), and tsvectorin().

◆ make_tsvector()

TSVector make_tsvector ( ParsedText prs)

Definition at line 165 of file to_tsany.c.

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 }
unsigned short uint16
Definition: c.h:505
#define SHORTALIGN(LEN)
Definition: c.h:807
#define ARRPTR(x)
Definition: cube.c:25
const char * str
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define STRPTR(x)
Definition: hstore.h:76
int j
Definition: isn.c:74
void * palloc0(Size size)
Definition: mcxt.c:1346
int32 curwords
Definition: ts_utils.h:106
ParsedWord * words
Definition: ts_utils.h:104
uint16 alen
Definition: ts_utils.h:87
uint16 len
Definition: ts_utils.h:85
uint16 pos
Definition: ts_utils.h:90
char * word
Definition: ts_utils.h:99
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
static int uniqueWORD(ParsedWord *a, int32 l)
Definition: to_tsany.c:77
TSVectorData * TSVector
Definition: ts_type.h:98
#define POSDATAPTR(x, e)
Definition: ts_type.h:111
#define MAXSTRPOS
Definition: ts_type.h:50

References ParsedWord::alen, ARRPTR, CALCDATASIZE, ParsedText::curwords, elog, ereport, errcode(), errmsg(), ERROR, WordEntry::haspos, i, j, WordEntry::len, ParsedWord::len, MAXSTRPOS, palloc0(), pfree(), WordEntry::pos, ParsedWord::pos, POSDATAPTR, SET_VARSIZE, SHORTALIGN, TSVectorData::size, str, STRPTR, uniqueWORD(), WEP_SETPOS, WEP_SETWEIGHT, ParsedWord::word, and ParsedText::words.

Referenced by json_to_tsvector_worker(), jsonb_to_tsvector_worker(), to_tsvector_byid(), and tsvector_update_trigger().

◆ makeTSQuerySign()

TSQuerySign makeTSQuerySign ( TSQuery  a)

Definition at line 250 of file tsquery_op.c.

251 {
252  int i;
253  QueryItem *ptr = GETQUERY(a);
254  TSQuerySign sign = 0;
255 
256  for (i = 0; i < a->size; i++)
257  {
258  if (ptr->type == QI_VAL)
259  sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
260  ptr++;
261  }
262 
263  return sign;
264 }
char sign
Definition: informix.c:674
int a
Definition: isn.c:69
int32 valcrc
Definition: ts_type.h:164
#define TSQS_SIGLEN
Definition: ts_utils.h:251
QueryOperand qoperand
Definition: ts_type.h:210
QueryItemType type
Definition: ts_type.h:208

References a, GETQUERY, i, QI_VAL, QueryItem::qoperand, sign, TSQS_SIGLEN, QueryItem::type, and QueryOperand::valcrc.

Referenced by gtsquery_compress(), and gtsquery_consistent().

◆ parse_tsquery()

TSQuery parse_tsquery ( char *  buf,
PushFunction  pushval,
Datum  opaque,
int  flags,
Node escontext 
)

Definition at line 821 of file tsquery.c.

826 {
828  int i;
829  TSQuery query;
830  int commonlen;
831  QueryItem *ptr;
832  ListCell *cell;
833  bool noisy;
834  bool needcleanup;
835  int tsv_flags = P_TSV_OPR_IS_DELIM | P_TSV_IS_TSQUERY;
836 
837  /* plain should not be used with web */
838  Assert((flags & (P_TSQ_PLAIN | P_TSQ_WEB)) != (P_TSQ_PLAIN | P_TSQ_WEB));
839 
840  /* select suitable tokenizer */
841  if (flags & P_TSQ_PLAIN)
842  state.gettoken = gettoken_query_plain;
843  else if (flags & P_TSQ_WEB)
844  {
845  state.gettoken = gettoken_query_websearch;
846  tsv_flags |= P_TSV_IS_WEB;
847  }
848  else
849  state.gettoken = gettoken_query_standard;
850 
851  /* emit nuisance NOTICEs only if not doing soft errors */
852  noisy = !(escontext && IsA(escontext, ErrorSaveContext));
853 
854  /* init state */
855  state.buffer = buf;
856  state.buf = buf;
857  state.count = 0;
858  state.state = WAITFIRSTOPERAND;
859  state.polstr = NIL;
860  state.escontext = escontext;
861 
862  /* init value parser's state */
863  state.valstate = init_tsvector_parser(state.buffer, tsv_flags, escontext);
864 
865  /* init list of operand */
866  state.sumlen = 0;
867  state.lenop = 64;
868  state.curop = state.op = (char *) palloc(state.lenop);
869  *(state.curop) = '\0';
870 
871  /* parse query & make polish notation (postfix, but in reverse order) */
872  makepol(&state, pushval, opaque);
873 
874  close_tsvector_parser(state.valstate);
875 
877  return NULL;
878 
879  if (state.polstr == NIL)
880  {
881  if (noisy)
882  ereport(NOTICE,
883  (errmsg("text-search query doesn't contain lexemes: \"%s\"",
884  state.buffer)));
885  query = (TSQuery) palloc(HDRSIZETQ);
886  SET_VARSIZE(query, HDRSIZETQ);
887  query->size = 0;
888  return query;
889  }
890 
891  if (TSQUERY_TOO_BIG(list_length(state.polstr), state.sumlen))
892  ereturn(escontext, NULL,
893  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
894  errmsg("tsquery is too large")));
895  commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen);
896 
897  /* Pack the QueryItems in the final TSQuery struct to return to caller */
898  query = (TSQuery) palloc0(commonlen);
899  SET_VARSIZE(query, commonlen);
900  query->size = list_length(state.polstr);
901  ptr = GETQUERY(query);
902 
903  /* Copy QueryItems to TSQuery */
904  i = 0;
905  foreach(cell, state.polstr)
906  {
907  QueryItem *item = (QueryItem *) lfirst(cell);
908 
909  switch (item->type)
910  {
911  case QI_VAL:
912  memcpy(&ptr[i], item, sizeof(QueryOperand));
913  break;
914  case QI_VALSTOP:
915  ptr[i].type = QI_VALSTOP;
916  break;
917  case QI_OPR:
918  memcpy(&ptr[i], item, sizeof(QueryOperator));
919  break;
920  default:
921  elog(ERROR, "unrecognized QueryItem type: %d", item->type);
922  }
923  i++;
924  }
925 
926  /* Copy all the operand strings to TSQuery */
927  memcpy(GETOPERAND(query), state.op, state.sumlen);
928  pfree(state.op);
929 
930  /*
931  * Set left operand pointers for every operator. While we're at it,
932  * detect whether there are any QI_VALSTOP nodes.
933  */
934  findoprnd(ptr, query->size, &needcleanup);
935 
936  /*
937  * If there are QI_VALSTOP nodes, delete them and simplify the tree.
938  */
939  if (needcleanup)
940  query = cleanup_tsquery_stopwords(query, noisy);
941 
942  return query;
943 }
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static char * buf
Definition: pg_test_fsync.c:73
TSQueryData * TSQuery
Definition: ts_type.h:225
#define QI_OPR
Definition: ts_type.h:150
#define TSQUERY_TOO_BIG(size, lenofoperand)
Definition: ts_type.h:233
#define QI_VALSTOP
Definition: ts_type.h:151
#define P_TSQ_PLAIN
Definition: ts_utils.h:64
#define P_TSQ_WEB
Definition: ts_utils.h:65
static ts_tokentype gettoken_query_standard(TSQueryParserState state, int8 *operator, int *lenval, char **strval, int16 *weight, bool *prefix)
Definition: tsquery.c:286
static void findoprnd(QueryItem *ptr, int size, bool *needcleanup)
Definition: tsquery.c:788
@ WAITFIRSTOPERAND
Definition: tsquery.c:44
static void makepol(TSQueryParserState state, PushFunction pushval, Datum opaque)
Definition: tsquery.c:676
static ts_tokentype gettoken_query_plain(TSQueryParserState state, int8 *operator, int *lenval, char **strval, int16 *weight, bool *prefix)
Definition: tsquery.c:514
static ts_tokentype gettoken_query_websearch(TSQueryParserState state, int8 *operator, int *lenval, char **strval, int16 *weight, bool *prefix)
Definition: tsquery.c:398
TSQuery cleanup_tsquery_stopwords(TSQuery in, bool noisy)
void close_tsvector_parser(TSVectorParseState state)
TSVectorParseState init_tsvector_parser(char *input, int flags, Node *escontext)

References Assert, buf, cleanup_tsquery_stopwords(), close_tsvector_parser(), COMPUTESIZE, elog, ereport, ereturn, errcode(), errmsg(), ERROR, TSQueryParserStateData::escontext, findoprnd(), GETOPERAND, GETQUERY, gettoken_query_plain(), gettoken_query_standard(), gettoken_query_websearch(), HDRSIZETQ, i, init_tsvector_parser(), IsA, lfirst, list_length(), makepol(), NIL, NOTICE, P_TSQ_PLAIN, P_TSQ_WEB, P_TSV_IS_TSQUERY, P_TSV_IS_WEB, P_TSV_OPR_IS_DELIM, palloc(), palloc0(), pfree(), QI_OPR, QI_VAL, QI_VALSTOP, SET_VARSIZE, TSQueryData::size, SOFT_ERROR_OCCURRED, TSQUERY_TOO_BIG, QueryItem::type, and WAITFIRSTOPERAND.

Referenced by phraseto_tsquery_byid(), plainto_tsquery_byid(), to_tsquery_byid(), tsqueryin(), and websearch_to_tsquery_byid().

◆ parsetext()

void parsetext ( Oid  cfgId,
ParsedText prs,
char *  buf,
int32  buflen 
)

◆ pushOperator()

void pushOperator ( TSQueryParserState  state,
int8  oper,
int16  distance 
)

Definition at line 535 of file tsquery.c.

536 {
537  QueryOperator *tmp;
538 
539  Assert(oper == OP_NOT || oper == OP_AND || oper == OP_OR || oper == OP_PHRASE);
540 
541  tmp = (QueryOperator *) palloc0(sizeof(QueryOperator));
542  tmp->type = QI_OPR;
543  tmp->oper = oper;
544  tmp->distance = (oper == OP_PHRASE) ? distance : 0;
545  /* left is filled in later with findoprnd */
546 
547  state->polstr = lcons(tmp, state->polstr);
548 }
List * lcons(void *datum, List *list)
Definition: list.c:495
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:370
int16 distance
Definition: ts_type.h:196
QueryItemType type
Definition: ts_type.h:194
#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 OP_NOT
Definition: ts_type.h:179

References Assert, QueryOperator::distance, lcons(), OP_AND, OP_NOT, OP_OR, OP_PHRASE, oper(), QueryOperator::oper, palloc0(), QI_OPR, and QueryOperator::type.

Referenced by cleanOpStack(), and pushval_morph().

◆ pushStop()

void pushStop ( TSQueryParserState  state)

Definition at line 620 of file tsquery.c.

621 {
622  QueryOperand *tmp;
623 
624  tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
625  tmp->type = QI_VALSTOP;
626 
627  state->polstr = lcons(tmp, state->polstr);
628 }

References lcons(), palloc0(), QI_VALSTOP, and QueryOperand::type.

Referenced by gettoken_query_websearch(), and pushval_morph().

◆ pushValue()

void pushValue ( TSQueryParserState  state,
char *  strval,
int  lenval,
int16  weight,
bool  prefix 
)

Definition at line 584 of file tsquery.c.

585 {
586  pg_crc32 valcrc;
587 
588  if (lenval >= MAXSTRLEN)
589  ereturn(state->escontext,,
590  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
591  errmsg("word is too long in tsquery: \"%s\"",
592  state->buffer)));
593 
594  INIT_LEGACY_CRC32(valcrc);
595  COMP_LEGACY_CRC32(valcrc, strval, lenval);
596  FIN_LEGACY_CRC32(valcrc);
597  pushValue_internal(state, valcrc, state->curop - state->op, lenval, weight, prefix);
598 
599  /* append the value string to state.op, enlarging buffer if needed first */
600  while (state->curop - state->op + lenval + 1 >= state->lenop)
601  {
602  int used = state->curop - state->op;
603 
604  state->lenop *= 2;
605  state->op = (char *) repalloc(state->op, state->lenop);
606  state->curop = state->op + used;
607  }
608  memcpy(state->curop, strval, lenval);
609  state->curop += lenval;
610  *(state->curop) = '\0';
611  state->curop++;
612  state->sumlen += lenval + 1 /* \0 */ ;
613 }
uint32 pg_crc32
Definition: pg_crc.h:37
#define INIT_LEGACY_CRC32(crc)
Definition: pg_crc.h:79
#define COMP_LEGACY_CRC32(crc, data, len)
Definition: pg_crc.h:81
#define FIN_LEGACY_CRC32(crc)
Definition: pg_crc.h:80
#define MAXSTRLEN
Definition: ts_type.h:49
static void pushValue_internal(TSQueryParserState state, pg_crc32 valcrc, int distance, int lenval, int weight, bool prefix)
Definition: tsquery.c:551

References COMP_LEGACY_CRC32, ereturn, errcode(), errmsg(), FIN_LEGACY_CRC32, INIT_LEGACY_CRC32, MAXSTRLEN, pushValue_internal(), and repalloc().

Referenced by pushval_asis(), and pushval_morph().

◆ QT2QTN()

QTNode* QT2QTN ( QueryItem in,
char *  operand 
)

Definition at line 25 of file tsquery_util.c.

26 {
27  QTNode *node = (QTNode *) palloc0(sizeof(QTNode));
28 
29  /* since this function recurses, it could be driven to stack overflow. */
31 
32  node->valnode = in;
33 
34  if (in->type == QI_OPR)
35  {
36  node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
37  node->child[0] = QT2QTN(in + 1, operand);
38  node->sign = node->child[0]->sign;
39  if (in->qoperator.oper == OP_NOT)
40  node->nchild = 1;
41  else
42  {
43  node->nchild = 2;
44  node->child[1] = QT2QTN(in + in->qoperator.left, operand);
45  node->sign |= node->child[1]->sign;
46  }
47  }
48  else if (operand)
49  {
50  node->word = operand + in->qoperand.distance;
51  node->sign = ((uint32) 1) << (((unsigned int) in->qoperand.valcrc) % 32);
52  }
53 
54  return node;
55 }
unsigned int uint32
Definition: c.h:506
void check_stack_depth(void)
Definition: postgres.c:3531
int32 nchild
Definition: ts_utils.h:238
QueryItem * valnode
Definition: ts_utils.h:236
uint32 sign
Definition: ts_utils.h:240
char * word
Definition: ts_utils.h:239
struct QTNode ** child
Definition: ts_utils.h:241
uint32 left
Definition: ts_type.h:197
QTNode * QT2QTN(QueryItem *in, char *operand)
Definition: tsquery_util.c:25
QueryOperator qoperator
Definition: ts_type.h:209

References check_stack_depth(), QTNode::child, QueryOperand::distance, QueryOperator::left, QTNode::nchild, OP_NOT, QueryOperator::oper, palloc0(), QI_OPR, QueryItem::qoperand, QueryItem::qoperator, QTNode::sign, QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), join_tsqueries(), tsquery_not(), tsquery_rewrite(), and tsquery_rewrite_query().

◆ QTN2QT()

TSQuery QTN2QT ( QTNode in)

Definition at line 363 of file tsquery_util.c.

364 {
365  TSQuery out;
366  int len;
367  int sumlen = 0,
368  nnode = 0;
370 
371  cntsize(in, &sumlen, &nnode);
372 
373  if (TSQUERY_TOO_BIG(nnode, sumlen))
374  ereport(ERROR,
375  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
376  errmsg("tsquery is too large")));
377  len = COMPUTESIZE(nnode, sumlen);
378 
379  out = (TSQuery) palloc0(len);
380  SET_VARSIZE(out, len);
381  out->size = nnode;
382 
383  state.curitem = GETQUERY(out);
384  state.operand = state.curoperand = GETOPERAND(out);
385 
386  fillQT(&state, in);
387  return out;
388 }
static void cntsize(QTNode *in, int *sumlen, int *nnode)
Definition: tsquery_util.c:292
static void fillQT(QTN2QTState *state, QTNode *in)
Definition: tsquery_util.c:323

References cntsize(), COMPUTESIZE, ereport, errcode(), errmsg(), ERROR, fillQT(), GETOPERAND, GETQUERY, len, palloc0(), SET_VARSIZE, TSQueryData::size, and TSQUERY_TOO_BIG.

Referenced by tsquery_and(), tsquery_not(), tsquery_or(), tsquery_phrase_distance(), tsquery_rewrite(), and tsquery_rewrite_query().

◆ QTNBinary()

void QTNBinary ( QTNode in)

Definition at line 250 of file tsquery_util.c.

251 {
252  int i;
253 
254  /* since this function recurses, it could be driven to stack overflow. */
256 
257  if (in->valnode->type != QI_OPR)
258  return;
259 
260  for (i = 0; i < in->nchild; i++)
261  QTNBinary(in->child[i]);
262 
263  while (in->nchild > 2)
264  {
265  QTNode *nn = (QTNode *) palloc0(sizeof(QTNode));
266 
267  nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
268  nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
269 
270  nn->nchild = 2;
271  nn->flags = QTN_NEEDFREE;
272 
273  nn->child[0] = in->child[0];
274  nn->child[1] = in->child[1];
275  nn->sign = nn->child[0]->sign | nn->child[1]->sign;
276 
277  nn->valnode->type = in->valnode->type;
279 
280  in->child[0] = nn;
281  in->child[1] = in->child[in->nchild - 1];
282  in->nchild--;
283  }
284 }
uint32 flags
Definition: ts_utils.h:237
#define QTN_NEEDFREE
Definition: ts_utils.h:245
void QTNBinary(QTNode *in)
Definition: tsquery_util.c:250

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, QueryOperator::oper, palloc0(), QI_OPR, QueryItem::qoperator, QTN_NEEDFREE, QTNode::sign, QueryItem::type, and QTNode::valnode.

Referenced by tsquery_rewrite(), and tsquery_rewrite_query().

◆ QTNClearFlags()

void QTNClearFlags ( QTNode in,
uint32  flags 
)

Definition at line 434 of file tsquery_util.c.

435 {
436  /* since this function recurses, it could be driven to stack overflow. */
438 
439  in->flags &= ~flags;
440 
441  if (in->valnode->type != QI_VAL)
442  {
443  int i;
444 
445  for (i = 0; i < in->nchild; i++)
446  QTNClearFlags(in->child[i], flags);
447  }
448 }
void QTNClearFlags(QTNode *in, uint32 flags)
Definition: tsquery_util.c:434

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, QI_VAL, QueryItem::type, and QTNode::valnode.

Referenced by tsquery_rewrite_query().

◆ QTNCopy()

QTNode* QTNCopy ( QTNode in)

Definition at line 396 of file tsquery_util.c.

397 {
398  QTNode *out;
399 
400  /* since this function recurses, it could be driven to stack overflow. */
402 
403  out = (QTNode *) palloc(sizeof(QTNode));
404 
405  *out = *in;
406  out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
407  *(out->valnode) = *(in->valnode);
408  out->flags |= QTN_NEEDFREE;
409 
410  if (in->valnode->type == QI_VAL)
411  {
412  out->word = palloc(in->valnode->qoperand.length + 1);
413  memcpy(out->word, in->word, in->valnode->qoperand.length);
414  out->word[in->valnode->qoperand.length] = '\0';
415  out->flags |= QTN_WORDFREE;
416  }
417  else
418  {
419  int i;
420 
421  out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);
422 
423  for (i = 0; i < in->nchild; i++)
424  out->child[i] = QTNCopy(in->child[i]);
425  }
426 
427  return out;
428 }
#define QTN_WORDFREE
Definition: ts_utils.h:247
QTNode * QTNCopy(QTNode *in)
Definition: tsquery_util.c:396

References check_stack_depth(), QTNode::child, QTNode::flags, i, QueryOperand::length, QTNode::nchild, palloc(), QI_VAL, QueryItem::qoperand, QTN_NEEDFREE, QTN_WORDFREE, QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by findeq().

◆ QTNEq()

bool QTNEq ( QTNode a,
QTNode b 
)

Definition at line 183 of file tsquery_util.c.

184 {
185  uint32 sign = a->sign & b->sign;
186 
187  if (!(sign == a->sign && sign == b->sign))
188  return false;
189 
190  return (QTNodeCompare(a, b) == 0);
191 }
int b
Definition: isn.c:70
int QTNodeCompare(QTNode *an, QTNode *bn)
Definition: tsquery_util.c:97

References a, b, QTNodeCompare(), and sign.

Referenced by findeq().

◆ QTNFree()

void QTNFree ( QTNode in)

Definition at line 64 of file tsquery_util.c.

65 {
66  if (!in)
67  return;
68 
69  /* since this function recurses, it could be driven to stack overflow. */
71 
72  if (in->valnode->type == QI_VAL && in->word && (in->flags & QTN_WORDFREE) != 0)
73  pfree(in->word);
74 
75  if (in->valnode->type == QI_OPR)
76  {
77  int i;
78 
79  for (i = 0; i < in->nchild; i++)
80  QTNFree(in->child[i]);
81  }
82  if (in->child)
83  pfree(in->child);
84 
85  if (in->flags & QTN_NEEDFREE)
86  pfree(in->valnode);
87 
88  pfree(in);
89 }
void QTNFree(QTNode *in)
Definition: tsquery_util.c:64

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, pfree(), QI_OPR, QI_VAL, QTN_NEEDFREE, QTN_WORDFREE, QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), dofindsubquery(), findeq(), tsquery_and(), tsquery_not(), tsquery_or(), tsquery_phrase_distance(), tsquery_rewrite(), and tsquery_rewrite_query().

◆ QTNodeCompare()

int QTNodeCompare ( QTNode an,
QTNode bn 
)

Definition at line 97 of file tsquery_util.c.

98 {
99  /* since this function recurses, it could be driven to stack overflow. */
101 
102  if (an->valnode->type != bn->valnode->type)
103  return (an->valnode->type > bn->valnode->type) ? -1 : 1;
104 
105  if (an->valnode->type == QI_OPR)
106  {
107  QueryOperator *ao = &an->valnode->qoperator;
108  QueryOperator *bo = &bn->valnode->qoperator;
109 
110  if (ao->oper != bo->oper)
111  return (ao->oper > bo->oper) ? -1 : 1;
112 
113  if (an->nchild != bn->nchild)
114  return (an->nchild > bn->nchild) ? -1 : 1;
115 
116  {
117  int i,
118  res;
119 
120  for (i = 0; i < an->nchild; i++)
121  if ((res = QTNodeCompare(an->child[i], bn->child[i])) != 0)
122  return res;
123  }
124 
125  if (ao->oper == OP_PHRASE && ao->distance != bo->distance)
126  return (ao->distance > bo->distance) ? -1 : 1;
127 
128  return 0;
129  }
130  else if (an->valnode->type == QI_VAL)
131  {
132  QueryOperand *ao = &an->valnode->qoperand;
133  QueryOperand *bo = &bn->valnode->qoperand;
134 
135  if (ao->valcrc != bo->valcrc)
136  {
137  return (ao->valcrc > bo->valcrc) ? -1 : 1;
138  }
139 
140  return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
141  }
142  else
143  {
144  elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
145  return 0; /* keep compiler quiet */
146  }
147 }
int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
Definition: tsvector_op.c:1152

References check_stack_depth(), QTNode::child, QueryOperator::distance, elog, ERROR, i, QueryOperand::length, QTNode::nchild, OP_PHRASE, QueryOperator::oper, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, res, tsCompareString(), QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

Referenced by cmpQTN(), CompareTSQ(), findeq(), and QTNEq().

◆ QTNSort()

void QTNSort ( QTNode in)

Definition at line 163 of file tsquery_util.c.

164 {
165  int i;
166 
167  /* since this function recurses, it could be driven to stack overflow. */
169 
170  if (in->valnode->type != QI_OPR)
171  return;
172 
173  for (i = 0; i < in->nchild; i++)
174  QTNSort(in->child[i]);
175  if (in->nchild > 1 && in->valnode->qoperator.oper != OP_PHRASE)
176  qsort(in->child, in->nchild, sizeof(QTNode *), cmpQTN);
177 }
#define qsort(a, b, c, d)
Definition: port.h:449
void QTNSort(QTNode *in)
Definition: tsquery_util.c:163
static int cmpQTN(const void *a, const void *b)
Definition: tsquery_util.c:153

References check_stack_depth(), QTNode::child, cmpQTN(), i, QTNode::nchild, OP_PHRASE, QueryOperator::oper, QI_OPR, QueryItem::qoperator, qsort, QueryItem::type, and QTNode::valnode.

Referenced by findeq(), tsquery_rewrite(), and tsquery_rewrite_query().

◆ QTNTernary()

void QTNTernary ( QTNode in)

Definition at line 201 of file tsquery_util.c.

202 {
203  int i;
204 
205  /* since this function recurses, it could be driven to stack overflow. */
207 
208  if (in->valnode->type != QI_OPR)
209  return;
210 
211  for (i = 0; i < in->nchild; i++)
212  QTNTernary(in->child[i]);
213 
214  /* Only AND and OR are associative, so don't flatten other node types */
215  if (in->valnode->qoperator.oper != OP_AND &&
216  in->valnode->qoperator.oper != OP_OR)
217  return;
218 
219  for (i = 0; i < in->nchild; i++)
220  {
221  QTNode *cc = in->child[i];
222 
223  if (cc->valnode->type == QI_OPR &&
225  {
226  int oldnchild = in->nchild;
227 
228  in->nchild += cc->nchild - 1;
229  in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));
230 
231  if (i + 1 != oldnchild)
232  memmove(in->child + i + cc->nchild, in->child + i + 1,
233  (oldnchild - i - 1) * sizeof(QTNode *));
234 
235  memcpy(in->child + i, cc->child, cc->nchild * sizeof(QTNode *));
236  i += cc->nchild - 1;
237 
238  if (cc->flags & QTN_NEEDFREE)
239  pfree(cc->valnode);
240  pfree(cc);
241  }
242  }
243 }
void QTNTernary(QTNode *in)
Definition: tsquery_util.c:201

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, OP_AND, OP_OR, QueryOperator::oper, pfree(), QI_OPR, QueryItem::qoperator, QTN_NEEDFREE, repalloc(), QueryItem::type, and QTNode::valnode.

Referenced by tsquery_rewrite(), and tsquery_rewrite_query().

◆ reset_tsvector_parser()

void reset_tsvector_parser ( TSVectorParseState  state,
char *  input 
)

Definition at line 81 of file tsvector_parser.c.

82 {
83  state->prsbuf = input;
84 }

References input.

Referenced by gettoken_query_standard(), and gettoken_query_websearch().

◆ TS_execute()

bool TS_execute ( QueryItem curitem,
void *  arg,
uint32  flags,
TSExecuteCallback  chkcond 
)

Definition at line 1854 of file tsvector_op.c.

1856 {
1857  /*
1858  * If we get TS_MAYBE from the recursion, return true. We could only see
1859  * that result if the caller passed TS_EXEC_PHRASE_NO_POS, so there's no
1860  * need to check again.
1861  */
1862  return TS_execute_recurse(curitem, arg, flags, chkcond) != TS_NO;
1863 }
void * arg
static TSTernaryValue TS_execute_recurse(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
Definition: tsvector_op.c:1883

References arg, TS_execute_recurse(), and TS_NO.

Referenced by Cover(), gtsvector_consistent(), hlCover(), and ts_match_vq().

◆ TS_execute_locations()

List* TS_execute_locations ( QueryItem curitem,
void *  arg,
uint32  flags,
TSExecuteCallback  chkcond 
)

Definition at line 2007 of file tsvector_op.c.

2010 {
2011  List *result;
2012 
2013  /* No flags supported, as yet */
2014  Assert(flags == TS_EXEC_EMPTY);
2015  if (TS_execute_locations_recurse(curitem, arg, chkcond, &result))
2016  return result;
2017  return NIL;
2018 }
Definition: pg_list.h:54
#define TS_EXEC_EMPTY
Definition: ts_utils.h:188
static bool TS_execute_locations_recurse(QueryItem *curitem, void *arg, TSExecuteCallback chkcond, List **locations)
Definition: tsvector_op.c:2025

References arg, Assert, NIL, TS_EXEC_EMPTY, and TS_execute_locations_recurse().

Referenced by prsd_headline().

◆ TS_execute_ternary()

TSTernaryValue TS_execute_ternary ( QueryItem curitem,
void *  arg,
uint32  flags,
TSExecuteCallback  chkcond 
)

Definition at line 1871 of file tsvector_op.c.

1873 {
1874  return TS_execute_recurse(curitem, arg, flags, chkcond);
1875 }

References arg, and TS_execute_recurse().

Referenced by gin_tsquery_consistent(), and gin_tsquery_triconsistent().

◆ tsCompareString()

int32 tsCompareString ( char *  a,
int  lena,
char *  b,
int  lenb,
bool  prefix 
)

Definition at line 1152 of file tsvector_op.c.

1153 {
1154  int cmp;
1155 
1156  if (lena == 0)
1157  {
1158  if (prefix)
1159  cmp = 0; /* empty string is prefix of anything */
1160  else
1161  cmp = (lenb > 0) ? -1 : 0;
1162  }
1163  else if (lenb == 0)
1164  {
1165  cmp = (lena > 0) ? 1 : 0;
1166  }
1167  else
1168  {
1169  cmp = memcmp(a, b, Min((unsigned int) lena, (unsigned int) lenb));
1170 
1171  if (prefix)
1172  {
1173  if (cmp == 0 && lena > lenb)
1174  cmp = 1; /* a is longer, so not a prefix of b */
1175  }
1176  else if (cmp == 0 && lena != lenb)
1177  {
1178  cmp = (lena < lenb) ? -1 : 1;
1179  }
1180  }
1181 
1182  return cmp;
1183 }
#define Min(x, y)
Definition: c.h:1004
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References a, b, cmp(), and Min.

Referenced by checkcondition_str(), compare_text_lexemes(), compareentry(), compareQueryOperand(), compareWORD(), gin_cmp_prefix(), gin_cmp_tslexeme(), hlfinditem(), QTNodeCompare(), silly_cmp_tsvector(), and tsvector_bsearch().

◆ tsquery_requires_match()

bool tsquery_requires_match ( QueryItem curitem)

Definition at line 2156 of file tsvector_op.c.

2157 {
2158  /* since this function recurses, it could be driven to stack overflow */
2160 
2161  if (curitem->type == QI_VAL)
2162  return true;
2163 
2164  switch (curitem->qoperator.oper)
2165  {
2166  case OP_NOT:
2167 
2168  /*
2169  * Assume there are no required matches underneath a NOT. For
2170  * some cases with nested NOTs, we could prove there's a required
2171  * match, but it seems unlikely to be worth the trouble.
2172  */
2173  return false;
2174 
2175  case OP_PHRASE:
2176 
2177  /*
2178  * Treat OP_PHRASE as OP_AND here
2179  */
2180  case OP_AND:
2181  /* If either side requires a match, we're good */
2182  if (tsquery_requires_match(curitem + curitem->qoperator.left))
2183  return true;
2184  else
2185  return tsquery_requires_match(curitem + 1);
2186 
2187  case OP_OR:
2188  /* Both sides must require a match */
2189  if (tsquery_requires_match(curitem + curitem->qoperator.left))
2190  return tsquery_requires_match(curitem + 1);
2191  else
2192  return false;
2193 
2194  default:
2195  elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
2196  }
2197 
2198  /* not reachable, but keep compiler quiet */
2199  return false;
2200 }
bool tsquery_requires_match(QueryItem *curitem)
Definition: tsvector_op.c:2156

References check_stack_depth(), elog, ERROR, QueryOperator::left, OP_AND, OP_NOT, OP_OR, OP_PHRASE, QueryOperator::oper, QI_VAL, QueryItem::qoperator, and QueryItem::type.

Referenced by gin_extract_tsquery().

◆ TSQuerySignGetDatum()

static Datum TSQuerySignGetDatum ( TSQuerySign  X)
inlinestatic

Definition at line 254 of file ts_utils.h.

255 {
256  return Int64GetDatum((int64) X);
257 }
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807

References Int64GetDatum().

Referenced by gtsquery_compress(), and gtsquery_picksplit().