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:69
int a
Definition: isn.c:68
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:72
void check_stack_depth(void)
Definition: stack_depth.c:95
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, cntsize(), i, QueryOperand::length, QTNode::nchild, QI_OPR, QueryItem::qoperand, QueryItem::type, and QTNode::valnode.

Referenced by cntsize(), and 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:815
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, fillQT(), QueryOperator::left, QueryOperand::length, QTNode::nchild, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by fillQT(), and 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}
uint32_t uint32
Definition: c.h:488
void * palloc0(Size size)
Definition: mcxt.c:1347
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, QT2QTN(), QTNode::sign, QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), join_tsqueries(), QT2QTN(), 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))
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:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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, QTNBinary(), QTNode::sign, QueryItem::type, and QTNode::valnode.

Referenced by QTNBinary(), 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, QTNClearFlags(), QueryItem::type, and QTNode::valnode.

Referenced by QTNClearFlags(), and 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:1317
#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, QTNCopy(), QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by findeq(), and QTNCopy().

◆ 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:693

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:1521
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, QTNFree(), QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), dofindsubquery(), findeq(), QTNFree(), 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:225
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, QTNodeCompare(), res, tsCompareString(), QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

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

◆ 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:474
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, QTNSort(), QueryItem::type, and QTNode::valnode.

Referenced by findeq(), QTNSort(), 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:1541
#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, QTNTernary(), repalloc(), QueryItem::type, and QTNode::valnode.

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