1
/*-------------------------------------------------------------------------
4
* Cleanup query from NOT values and/or stopword
5
* Utility functions to correct work.
7
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
13
*-------------------------------------------------------------------------
18
#include "tsearch/ts_type.h"
19
#include "tsearch/ts_utils.h"
20
#include "miscadmin.h"
30
* make query tree from plain view of query
33
maketree(QueryItem *in)
35
NODE *node = (NODE *) palloc(sizeof(NODE));
38
node->right = node->left = NULL;
39
if (in->type == QI_OPR)
41
node->right = maketree(in + 1);
42
if (in->operator.oper != OP_NOT)
43
node->left = maketree(in + in->operator.left);
49
* Internal state for plaintree and plainnode
54
int len; /* allocated size of ptr */
55
int cur; /* number of elements in ptr */
59
plainnode(PLAINTREE *state, NODE *node)
61
/* since this function recurses, it could be driven to stack overflow. */
64
if (state->cur == state->len)
67
state->ptr = (QueryItem *) repalloc((void *) state->ptr, state->len * sizeof(QueryItem));
69
memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(QueryItem));
70
if (node->valnode->type == QI_VAL)
72
else if (node->valnode->operator.oper == OP_NOT)
74
state->ptr[state->cur].operator.left = 1;
76
plainnode(state, node->right);
83
plainnode(state, node->right);
84
state->ptr[cur].operator.left = state->cur - cur;
85
plainnode(state, node->left);
91
* make plain view of tree from a NODE-tree representation
94
plaintree(NODE *root, int *len)
100
if (root && (root->valnode->type == QI_VAL || root->valnode->type == QI_OPR))
102
pl.ptr = (QueryItem *) palloc(pl.len * sizeof(QueryItem));
103
plainnode(&pl, root);
114
/* since this function recurses, it could be driven to stack overflow. */
120
freetree(node->left);
122
freetree(node->right);
127
* clean tree for ! operator.
128
* It's usefull for debug, but in
129
* other case, such view is used with search in index.
130
* Operator ! always return TRUE
133
clean_NOT_intree(NODE *node)
135
/* since this function recurses, it could be driven to stack overflow. */
138
if (node->valnode->type == QI_VAL)
141
if (node->valnode->operator.oper == OP_NOT)
147
/* operator & or | */
148
if (node->valnode->operator.oper == OP_OR)
150
if ((node->left = clean_NOT_intree(node->left)) == NULL ||
151
(node->right = clean_NOT_intree(node->right)) == NULL)
161
Assert(node->valnode->operator.oper == OP_AND);
163
node->left = clean_NOT_intree(node->left);
164
node->right = clean_NOT_intree(node->right);
165
if (node->left == NULL && node->right == NULL)
170
else if (node->left == NULL)
175
else if (node->right == NULL)
186
clean_NOT(QueryItem *ptr, int *len)
188
NODE *root = maketree(ptr);
190
return plaintree(clean_NOT_intree(root), len);
194
#ifdef V_UNKNOWN /* exists in Windows headers */
197
#ifdef V_FALSE /* exists in Solaris headers */
202
* output values for result output parameter of clean_fakeval_intree
204
#define V_UNKNOWN 0 /* the expression can't be evaluated
206
#define V_TRUE 1 /* the expression is always true (not
208
#define V_FALSE 2 /* the expression is always false (not
210
#define V_STOP 3 /* the expression is a stop word */
213
* Clean query tree from values which is always in
217
clean_fakeval_intree(NODE *node, char *result)
219
char lresult = V_UNKNOWN,
222
/* since this function recurses, it could be driven to stack overflow. */
225
if (node->valnode->type == QI_VAL)
227
else if (node->valnode->type == QI_VALSTOP)
234
Assert(node->valnode->type == QI_OPR);
236
if (node->valnode->operator.oper == OP_NOT)
238
node->right = clean_fakeval_intree(node->right, &rresult);
250
node->left = clean_fakeval_intree(node->left, &lresult);
251
node->right = clean_fakeval_intree(node->right, &rresult);
253
if (lresult == V_STOP && rresult == V_STOP)
259
else if (lresult == V_STOP)
264
else if (rresult == V_STOP)
275
clean_fakeval(QueryItem *ptr, int *len)
277
NODE *root = maketree(ptr);
278
char result = V_UNKNOWN;
281
resroot = clean_fakeval_intree(root, &result);
282
if (result != V_UNKNOWN)
285
(errmsg("text-search query contains only stop words or doesn't contain lexemes, ignored")));
290
return plaintree(resroot, len);