PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tsquery_cleanup.c File Reference
#include "postgres.h"
#include "tsearch/ts_utils.h"
#include "miscadmin.h"
Include dependency graph for tsquery_cleanup.c:

Go to the source code of this file.

Data Structures

struct  NODE
 
struct  PLAINTREE
 

Typedefs

typedef struct NODE NODE
 

Functions

static NODEmaketree (QueryItem *in)
 
static void plainnode (PLAINTREE *state, NODE *node)
 
static QueryItemplaintree (NODE *root, int *len)
 
static void freetree (NODE *node)
 
static NODEclean_NOT_intree (NODE *node)
 
QueryItemclean_NOT (QueryItem *ptr, int *len)
 
static NODEclean_stopword_intree (NODE *node, int *ladd, int *radd)
 
static int32 calcstrlen (NODE *node)
 
TSQuery cleanup_tsquery_stopwords (TSQuery in)
 

Typedef Documentation

typedef struct NODE NODE

Function Documentation

static int32 calcstrlen ( NODE node)
static

Definition at line 362 of file tsquery_cleanup.c.

References Assert, NODE::left, QueryOperand::length, OP_NOT, QueryOperator::oper, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, NODE::right, QueryItem::type, and NODE::valnode.

Referenced by cleanup_tsquery_stopwords().

363 {
364  int32 size = 0;
365 
366  if (node->valnode->type == QI_VAL)
367  {
368  size = node->valnode->qoperand.length + 1;
369  }
370  else
371  {
372  Assert(node->valnode->type == QI_OPR);
373 
374  size = calcstrlen(node->right);
375  if (node->valnode->qoperator.oper != OP_NOT)
376  size += calcstrlen(node->left);
377  }
378 
379  return size;
380 }
QueryOperator qoperator
Definition: ts_type.h:196
struct NODE * left
QueryItem * valnode
struct NODE * right
#define QI_VAL
Definition: ts_type.h:134
signed int int32
Definition: c.h:256
#define QI_OPR
Definition: ts_type.h:135
QueryItemType type
Definition: ts_type.h:195
#define Assert(condition)
Definition: c.h:675
static int32 calcstrlen(NODE *node)
uint32 length
Definition: ts_type.h:158
QueryOperand qoperand
Definition: ts_type.h:197
#define OP_NOT
Definition: ts_type.h:166
QueryItem* clean_NOT ( QueryItem ptr,
int *  len 
)

Definition at line 189 of file tsquery_cleanup.c.

References clean_NOT_intree(), maketree(), and plaintree().

Referenced by tsquerytree().

190 {
191  NODE *root = maketree(ptr);
192 
193  return plaintree(clean_NOT_intree(root), len);
194 }
Definition: _int_bool.c:27
static NODE * clean_NOT_intree(NODE *node)
static QueryItem * plaintree(NODE *root, int *len)
static NODE * maketree(QueryItem *in)
static NODE* clean_NOT_intree ( NODE node)
static

Definition at line 135 of file tsquery_cleanup.c.

References Assert, check_stack_depth(), freetree(), NODE::left, NULL, OP_AND, OP_NOT, OP_OR, OP_PHRASE, QueryOperator::oper, pfree(), QI_VAL, QueryItem::qoperator, NODE::right, QueryItem::type, and NODE::valnode.

Referenced by clean_NOT().

136 {
137  /* since this function recurses, it could be driven to stack overflow. */
139 
140  if (node->valnode->type == QI_VAL)
141  return node;
142 
143  if (node->valnode->qoperator.oper == OP_NOT)
144  {
145  freetree(node);
146  return NULL;
147  }
148 
149  /* operator & or | */
150  if (node->valnode->qoperator.oper == OP_OR)
151  {
152  if ((node->left = clean_NOT_intree(node->left)) == NULL ||
153  (node->right = clean_NOT_intree(node->right)) == NULL)
154  {
155  freetree(node);
156  return NULL;
157  }
158  }
159  else
160  {
161  NODE *res = node;
162 
163  Assert(node->valnode->qoperator.oper == OP_AND ||
164  node->valnode->qoperator.oper == OP_PHRASE);
165 
166  node->left = clean_NOT_intree(node->left);
167  node->right = clean_NOT_intree(node->right);
168  if (node->left == NULL && node->right == NULL)
169  {
170  pfree(node);
171  res = NULL;
172  }
173  else if (node->left == NULL)
174  {
175  res = node->right;
176  pfree(node);
177  }
178  else if (node->right == NULL)
179  {
180  res = node->left;
181  pfree(node);
182  }
183  return res;
184  }
185  return node;
186 }
QueryOperator qoperator
Definition: ts_type.h:196
Definition: _int_bool.c:27
struct NODE * left
QueryItem * valnode
struct NODE * right
#define QI_VAL
Definition: ts_type.h:134
#define OP_OR
Definition: ts_type.h:168
static NODE * clean_NOT_intree(NODE *node)
#define OP_AND
Definition: ts_type.h:167
void pfree(void *pointer)
Definition: mcxt.c:950
void check_stack_depth(void)
Definition: postgres.c:3117
QueryItemType type
Definition: ts_type.h:195
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void freetree(NODE *node)
#define OP_PHRASE
Definition: ts_type.h:169
#define OP_NOT
Definition: ts_type.h:166
static NODE* clean_stopword_intree ( NODE node,
int *  ladd,
int *  radd 
)
static

Definition at line 237 of file tsquery_cleanup.c.

References Assert, check_stack_depth(), QueryOperator::distance, freetree(), NODE::left, Max, NULL, OP_NOT, OP_PHRASE, QueryOperator::oper, pfree(), QI_OPR, QI_VAL, QI_VALSTOP, QueryItem::qoperator, NODE::right, QueryItem::type, and NODE::valnode.

Referenced by cleanup_tsquery_stopwords().

238 {
239  /* since this function recurses, it could be driven to stack overflow. */
241 
242  /* default output parameters indicate no change in parent distance */
243  *ladd = *radd = 0;
244 
245  if (node->valnode->type == QI_VAL)
246  return node;
247  else if (node->valnode->type == QI_VALSTOP)
248  {
249  pfree(node);
250  return NULL;
251  }
252 
253  Assert(node->valnode->type == QI_OPR);
254 
255  if (node->valnode->qoperator.oper == OP_NOT)
256  {
257  /* NOT doesn't change pattern width, so just report child distances */
258  node->right = clean_stopword_intree(node->right, ladd, radd);
259  if (!node->right)
260  {
261  freetree(node);
262  return NULL;
263  }
264  }
265  else
266  {
267  NODE *res = node;
268  bool isphrase;
269  int ndistance,
270  lladd,
271  lradd,
272  rladd,
273  rradd;
274 
275  /* First, recurse */
276  node->left = clean_stopword_intree(node->left, &lladd, &lradd);
277  node->right = clean_stopword_intree(node->right, &rladd, &rradd);
278 
279  /* Check if current node is OP_PHRASE, get its distance */
280  isphrase = (node->valnode->qoperator.oper == OP_PHRASE);
281  ndistance = isphrase ? node->valnode->qoperator.distance : 0;
282 
283  if (node->left == NULL && node->right == NULL)
284  {
285  /*
286  * When we collapse out a phrase node entirely, propagate its own
287  * distance into both *ladd and *radd; it is the responsibility of
288  * the parent node to count it only once. Also, for a phrase
289  * node, distances coming from children are summed and propagated
290  * up to parent (we assume lladd == lradd and rladd == rradd, else
291  * rule was broken at a lower level). But if this isn't a phrase
292  * node, take the larger of the two child distances; that
293  * corresponds to what TS_execute will do in non-stopword cases.
294  */
295  if (isphrase)
296  *ladd = *radd = lladd + ndistance + rladd;
297  else
298  *ladd = *radd = Max(lladd, rladd);
299  freetree(node);
300  return NULL;
301  }
302  else if (node->left == NULL)
303  {
304  /* Removing this operator and left subnode */
305  /* lladd and lradd are equal/redundant, don't count both */
306  if (isphrase)
307  {
308  /* operator's own distance must propagate to left */
309  *ladd = lladd + ndistance + rladd;
310  *radd = rradd;
311  }
312  else
313  {
314  /* at non-phrase op, just forget the left subnode entirely */
315  *ladd = rladd;
316  *radd = rradd;
317  }
318  res = node->right;
319  pfree(node);
320  }
321  else if (node->right == NULL)
322  {
323  /* Removing this operator and right subnode */
324  /* rladd and rradd are equal/redundant, don't count both */
325  if (isphrase)
326  {
327  /* operator's own distance must propagate to right */
328  *ladd = lladd;
329  *radd = lradd + ndistance + rradd;
330  }
331  else
332  {
333  /* at non-phrase op, just forget the right subnode entirely */
334  *ladd = lladd;
335  *radd = lradd;
336  }
337  res = node->left;
338  pfree(node);
339  }
340  else if (isphrase)
341  {
342  /* Absorb appropriate corrections at this level */
343  node->valnode->qoperator.distance += lradd + rladd;
344  /* Propagate up any unaccounted-for corrections */
345  *ladd = lladd;
346  *radd = rradd;
347  }
348  else
349  {
350  /* We're keeping a non-phrase operator, so ladd/radd remain 0 */
351  }
352 
353  return res;
354  }
355  return node;
356 }
#define QI_VALSTOP
Definition: ts_type.h:136
QueryOperator qoperator
Definition: ts_type.h:196
Definition: _int_bool.c:27
static NODE * clean_stopword_intree(NODE *node, int *ladd, int *radd)
struct NODE * left
QueryItem * valnode
struct NODE * right
#define QI_VAL
Definition: ts_type.h:134
int16 distance
Definition: ts_type.h:183
void pfree(void *pointer)
Definition: mcxt.c:950
void check_stack_depth(void)
Definition: postgres.c:3117
#define QI_OPR
Definition: ts_type.h:135
QueryItemType type
Definition: ts_type.h:195
#define Max(x, y)
Definition: c.h:800
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void freetree(NODE *node)
#define OP_PHRASE
Definition: ts_type.h:169
#define OP_NOT
Definition: ts_type.h:166
TSQuery cleanup_tsquery_stopwords ( TSQuery  in)

Definition at line 386 of file tsquery_cleanup.c.

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

Referenced by parse_tsquery().

387 {
388  int32 len,
389  lenstr,
390  commonlen,
391  i;
392  NODE *root;
393  int ladd,
394  radd;
395  TSQuery out;
396  QueryItem *items;
397  char *operands;
398 
399  if (in->size == 0)
400  return in;
401 
402  /* eliminate stop words */
403  root = clean_stopword_intree(maketree(GETQUERY(in)), &ladd, &radd);
404  if (root == NULL)
405  {
406  ereport(NOTICE,
407  (errmsg("text-search query contains only stop words or doesn't contain lexemes, ignored")));
408  out = palloc(HDRSIZETQ);
409  out->size = 0;
410  SET_VARSIZE(out, HDRSIZETQ);
411  return out;
412  }
413 
414  /*
415  * Build TSQuery from plain view
416  */
417 
418  lenstr = calcstrlen(root);
419  items = plaintree(root, &len);
420  commonlen = COMPUTESIZE(len, lenstr);
421 
422  out = palloc(commonlen);
423  SET_VARSIZE(out, commonlen);
424  out->size = len;
425 
426  memcpy(GETQUERY(out), items, len * sizeof(QueryItem));
427 
428  items = GETQUERY(out);
429  operands = GETOPERAND(out);
430  for (i = 0; i < out->size; i++)
431  {
432  QueryOperand *op = (QueryOperand *) &items[i];
433 
434  if (op->type != QI_VAL)
435  continue;
436 
437  memcpy(operands, GETOPERAND(in) + op->distance, op->length);
438  operands[op->length] = '\0';
439  op->distance = operands - GETOPERAND(out);
440  operands += op->length + 1;
441  }
442 
443  return out;
444 }
Definition: _int_bool.c:27
static NODE * clean_stopword_intree(NODE *node, int *ladd, int *radd)
#define QI_VAL
Definition: ts_type.h:134
uint32 distance
Definition: ts_type.h:158
#define GETQUERY(x)
Definition: _int.h:142
signed int int32
Definition: c.h:256
#define GETOPERAND(x)
Definition: ltree.h:118
static QueryItem * plaintree(NODE *root, int *len)
#define ereport(elevel, rest)
Definition: elog.h:122
#define COMPUTESIZE(size)
Definition: _int.h:140
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:229
static int32 calcstrlen(NODE *node)
uint32 length
Definition: ts_type.h:158
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 size
Definition: ts_type.h:208
int i
QueryItemType type
Definition: ts_type.h:145
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
static NODE * maketree(QueryItem *in)
#define HDRSIZETQ
Definition: ts_type.h:214
static void freetree ( NODE node)
static

Definition at line 114 of file tsquery_cleanup.c.

References check_stack_depth(), NODE::left, pfree(), and NODE::right.

Referenced by clean_NOT_intree(), and clean_stopword_intree().

115 {
116  /* since this function recurses, it could be driven to stack overflow. */
118 
119  if (!node)
120  return;
121  if (node->left)
122  freetree(node->left);
123  if (node->right)
124  freetree(node->right);
125  pfree(node);
126 }
struct NODE * left
struct NODE * right
void pfree(void *pointer)
Definition: mcxt.c:950
void check_stack_depth(void)
Definition: postgres.c:3117
static void freetree(NODE *node)
static NODE* maketree ( QueryItem in)
static

Definition at line 32 of file tsquery_cleanup.c.

References check_stack_depth(), NODE::left, QueryOperator::left, NULL, OP_NOT, QueryOperator::oper, palloc(), QI_OPR, QueryItem::qoperator, NODE::right, QueryItem::type, and NODE::valnode.

Referenced by clean_NOT(), and cleanup_tsquery_stopwords().

33 {
34  NODE *node = (NODE *) palloc(sizeof(NODE));
35 
36  /* since this function recurses, it could be driven to stack overflow. */
38 
39  node->valnode = in;
40  node->right = node->left = NULL;
41  if (in->type == QI_OPR)
42  {
43  node->right = maketree(in + 1);
44  if (in->qoperator.oper != OP_NOT)
45  node->left = maketree(in + in->qoperator.left);
46  }
47  return node;
48 }
QueryOperator qoperator
Definition: ts_type.h:196
Definition: _int_bool.c:27
struct NODE * left
QueryItem * valnode
struct NODE * right
void check_stack_depth(void)
Definition: postgres.c:3117
#define QI_OPR
Definition: ts_type.h:135
QueryItemType type
Definition: ts_type.h:195
#define NULL
Definition: c.h:229
uint32 left
Definition: ts_type.h:184
void * palloc(Size size)
Definition: mcxt.c:849
static NODE * maketree(QueryItem *in)
#define OP_NOT
Definition: ts_type.h:166
static void plainnode ( PLAINTREE state,
NODE node 
)
static

Definition at line 61 of file tsquery_cleanup.c.

References check_stack_depth(), cur, PLAINTREE::cur, NODE::left, QueryOperator::left, PLAINTREE::len, OP_NOT, QueryOperator::oper, pfree(), PLAINTREE::ptr, QI_VAL, QueryItem::qoperator, repalloc(), NODE::right, QueryItem::type, and NODE::valnode.

Referenced by plaintree().

62 {
63  /* since this function recurses, it could be driven to stack overflow. */
65 
66  if (state->cur == state->len)
67  {
68  state->len *= 2;
69  state->ptr = (QueryItem *) repalloc((void *) state->ptr, state->len * sizeof(QueryItem));
70  }
71  memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(QueryItem));
72  if (node->valnode->type == QI_VAL)
73  state->cur++;
74  else if (node->valnode->qoperator.oper == OP_NOT)
75  {
76  state->ptr[state->cur].qoperator.left = 1;
77  state->cur++;
78  plainnode(state, node->right);
79  }
80  else
81  {
82  int cur = state->cur;
83 
84  state->cur++;
85  plainnode(state, node->right);
86  state->ptr[cur].qoperator.left = state->cur - cur;
87  plainnode(state, node->left);
88  }
89  pfree(node);
90 }
QueryOperator qoperator
Definition: ts_type.h:196
struct NODE * left
QueryItem * ptr
QueryItem * valnode
struct cursor * cur
Definition: ecpg.c:28
struct NODE * right
#define QI_VAL
Definition: ts_type.h:134
void pfree(void *pointer)
Definition: mcxt.c:950
void check_stack_depth(void)
Definition: postgres.c:3117
QueryItemType type
Definition: ts_type.h:195
static void plainnode(PLAINTREE *state, NODE *node)
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
uint32 left
Definition: ts_type.h:184
#define OP_NOT
Definition: ts_type.h:166
static QueryItem* plaintree ( NODE root,
int *  len 
)
static

Definition at line 96 of file tsquery_cleanup.c.

References PLAINTREE::cur, PLAINTREE::len, NULL, palloc(), plainnode(), PLAINTREE::ptr, QI_OPR, QI_VAL, QueryItem::type, and NODE::valnode.

Referenced by clean_NOT(), and cleanup_tsquery_stopwords().

97 {
98  PLAINTREE pl;
99 
100  pl.cur = 0;
101  pl.len = 16;
102  if (root && (root->valnode->type == QI_VAL || root->valnode->type == QI_OPR))
103  {
104  pl.ptr = (QueryItem *) palloc(pl.len * sizeof(QueryItem));
105  plainnode(&pl, root);
106  }
107  else
108  pl.ptr = NULL;
109  *len = pl.cur;
110  return pl.ptr;
111 }
QueryItem * ptr
QueryItem * valnode
#define QI_VAL
Definition: ts_type.h:134
#define QI_OPR
Definition: ts_type.h:135
QueryItemType type
Definition: ts_type.h:195
static void plainnode(PLAINTREE *state, NODE *node)
#define NULL
Definition: c.h:229
void * palloc(Size size)
Definition: mcxt.c:849