PostgreSQL Source Code  git master
tsquery_util.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "tsearch/ts_utils.h"
#include "varatt.h"
Include dependency graph for tsquery_util.c:

Go to the source code of this file.

Data Structures

struct  QTN2QTState
 

Functions

QTNodeQT2QTN (QueryItem *in, char *operand)
 
void QTNFree (QTNode *in)
 
int QTNodeCompare (QTNode *an, QTNode *bn)
 
static int cmpQTN (const void *a, const void *b)
 
void QTNSort (QTNode *in)
 
bool QTNEq (QTNode *a, QTNode *b)
 
void QTNTernary (QTNode *in)
 
void QTNBinary (QTNode *in)
 
static void cntsize (QTNode *in, int *sumlen, int *nnode)
 
static void fillQT (QTN2QTState *state, QTNode *in)
 
TSQuery QTN2QT (QTNode *in)
 
QTNodeQTNCopy (QTNode *in)
 
void QTNClearFlags (QTNode *in, uint32 flags)
 

Function Documentation

◆ cmpQTN()

static int cmpQTN ( const void *  a,
const void *  b 
)
static

Definition at line 153 of file tsquery_util.c.

154 {
155  return QTNodeCompare(*(QTNode *const *) a, *(QTNode *const *) b);
156 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69
int QTNodeCompare(QTNode *an, QTNode *bn)
Definition: tsquery_util.c:97

References a, b, and QTNodeCompare().

Referenced by QTNSort().

◆ cntsize()

static void cntsize ( QTNode in,
int *  sumlen,
int *  nnode 
)
static

Definition at line 292 of file tsquery_util.c.

293 {
294  /* since this function recurses, it could be driven to stack overflow. */
296 
297  *nnode += 1;
298  if (in->valnode->type == QI_OPR)
299  {
300  int i;
301 
302  for (i = 0; i < in->nchild; i++)
303  cntsize(in->child[i], sumlen, nnode);
304  }
305  else
306  {
307  *sumlen += in->valnode->qoperand.length + 1;
308  }
309 }
int i
Definition: isn.c:73
void check_stack_depth(void)
Definition: postgres.c:3531
int32 nchild
Definition: ts_utils.h:238
QueryItem * valnode
Definition: ts_utils.h:236
struct QTNode ** child
Definition: ts_utils.h:241
uint32 length
Definition: ts_type.h:171
#define QI_OPR
Definition: ts_type.h:150
static void cntsize(QTNode *in, int *sumlen, int *nnode)
Definition: tsquery_util.c:292
QueryOperand qoperand
Definition: ts_type.h:210
QueryItemType type
Definition: ts_type.h:208

References check_stack_depth(), QTNode::child, i, QueryOperand::length, QTNode::nchild, QI_OPR, QueryItem::qoperand, QueryItem::type, and QTNode::valnode.

Referenced by QTN2QT().

◆ fillQT()

static void fillQT ( QTN2QTState state,
QTNode in 
)
static

Definition at line 323 of file tsquery_util.c.

324 {
325  /* since this function recurses, it could be driven to stack overflow. */
327 
328  if (in->valnode->type == QI_VAL)
329  {
330  memcpy(state->curitem, in->valnode, sizeof(QueryOperand));
331 
332  memcpy(state->curoperand, in->word, in->valnode->qoperand.length);
333  state->curitem->qoperand.distance = state->curoperand - state->operand;
334  state->curoperand[in->valnode->qoperand.length] = '\0';
335  state->curoperand += in->valnode->qoperand.length + 1;
336  state->curitem++;
337  }
338  else
339  {
340  QueryItem *curitem = state->curitem;
341 
342  Assert(in->valnode->type == QI_OPR);
343 
344  memcpy(state->curitem, in->valnode, sizeof(QueryOperator));
345 
346  Assert(in->nchild <= 2);
347  state->curitem++;
348 
349  fillQT(state, in->child[0]);
350 
351  if (in->nchild == 2)
352  {
353  curitem->qoperator.left = state->curitem - curitem;
354  fillQT(state, in->child[1]);
355  }
356  }
357 }
#define Assert(condition)
Definition: c.h:858
char * word
Definition: ts_utils.h:239
uint32 left
Definition: ts_type.h:197
Definition: regguts.h:323
#define QI_VAL
Definition: ts_type.h:149
static void fillQT(QTN2QTState *state, QTNode *in)
Definition: tsquery_util.c:323
QueryOperator qoperator
Definition: ts_type.h:209

References Assert, check_stack_depth(), QTNode::child, QueryOperator::left, QueryOperand::length, QTNode::nchild, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by QTN2QT().

◆ 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 * palloc0(Size size)
Definition: mcxt.c:1346
uint32 sign
Definition: ts_utils.h:240
uint32 distance
Definition: ts_type.h:172
int32 valcrc
Definition: ts_type.h:164
#define OP_NOT
Definition: ts_type.h:179
QTNode * QT2QTN(QueryItem *in, char *operand)
Definition: tsquery_util.c:25

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 }
#define COMPUTESIZE(size)
Definition: _int.h:155
#define GETQUERY(x)
Definition: _int.h:157
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define GETOPERAND(x)
Definition: ltree.h:165
const void size_t len
int32 size
Definition: ts_type.h:221
TSQueryData * TSQuery
Definition: ts_type.h:225
#define TSQUERY_TOO_BIG(size, lenofoperand)
Definition: ts_type.h:233
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

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 }
void * palloc(Size size)
Definition: mcxt.c:1316
#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 }
char sign
Definition: informix.c:674

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 pfree(void *pointer)
Definition: mcxt.c:1520
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 }
#define elog(elevel,...)
Definition: elog.h:224
int16 distance
Definition: ts_type.h:196
#define OP_PHRASE
Definition: ts_type.h:182
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 * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
#define OP_AND
Definition: ts_type.h:180
#define OP_OR
Definition: ts_type.h:181
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().