Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "tsearch/ts_utils.h"
00019 #include "miscadmin.h"
00020
00021 typedef struct NODE
00022 {
00023 struct NODE *left;
00024 struct NODE *right;
00025 QueryItem *valnode;
00026 } NODE;
00027
00028
00029
00030
00031 static NODE *
00032 maketree(QueryItem *in)
00033 {
00034 NODE *node = (NODE *) palloc(sizeof(NODE));
00035
00036 node->valnode = in;
00037 node->right = node->left = NULL;
00038 if (in->type == QI_OPR)
00039 {
00040 node->right = maketree(in + 1);
00041 if (in->qoperator.oper != OP_NOT)
00042 node->left = maketree(in + in->qoperator.left);
00043 }
00044 return node;
00045 }
00046
00047
00048
00049
00050 typedef struct
00051 {
00052 QueryItem *ptr;
00053 int len;
00054 int cur;
00055 } PLAINTREE;
00056
00057 static void
00058 plainnode(PLAINTREE *state, NODE *node)
00059 {
00060
00061 check_stack_depth();
00062
00063 if (state->cur == state->len)
00064 {
00065 state->len *= 2;
00066 state->ptr = (QueryItem *) repalloc((void *) state->ptr, state->len * sizeof(QueryItem));
00067 }
00068 memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(QueryItem));
00069 if (node->valnode->type == QI_VAL)
00070 state->cur++;
00071 else if (node->valnode->qoperator.oper == OP_NOT)
00072 {
00073 state->ptr[state->cur].qoperator.left = 1;
00074 state->cur++;
00075 plainnode(state, node->right);
00076 }
00077 else
00078 {
00079 int cur = state->cur;
00080
00081 state->cur++;
00082 plainnode(state, node->right);
00083 state->ptr[cur].qoperator.left = state->cur - cur;
00084 plainnode(state, node->left);
00085 }
00086 pfree(node);
00087 }
00088
00089
00090
00091
00092 static QueryItem *
00093 plaintree(NODE *root, int *len)
00094 {
00095 PLAINTREE pl;
00096
00097 pl.cur = 0;
00098 pl.len = 16;
00099 if (root && (root->valnode->type == QI_VAL || root->valnode->type == QI_OPR))
00100 {
00101 pl.ptr = (QueryItem *) palloc(pl.len * sizeof(QueryItem));
00102 plainnode(&pl, root);
00103 }
00104 else
00105 pl.ptr = NULL;
00106 *len = pl.cur;
00107 return pl.ptr;
00108 }
00109
00110 static void
00111 freetree(NODE *node)
00112 {
00113
00114 check_stack_depth();
00115
00116 if (!node)
00117 return;
00118 if (node->left)
00119 freetree(node->left);
00120 if (node->right)
00121 freetree(node->right);
00122 pfree(node);
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 static NODE *
00132 clean_NOT_intree(NODE *node)
00133 {
00134
00135 check_stack_depth();
00136
00137 if (node->valnode->type == QI_VAL)
00138 return node;
00139
00140 if (node->valnode->qoperator.oper == OP_NOT)
00141 {
00142 freetree(node);
00143 return NULL;
00144 }
00145
00146
00147 if (node->valnode->qoperator.oper == OP_OR)
00148 {
00149 if ((node->left = clean_NOT_intree(node->left)) == NULL ||
00150 (node->right = clean_NOT_intree(node->right)) == NULL)
00151 {
00152 freetree(node);
00153 return NULL;
00154 }
00155 }
00156 else
00157 {
00158 NODE *res = node;
00159
00160 Assert(node->valnode->qoperator.oper == OP_AND);
00161
00162 node->left = clean_NOT_intree(node->left);
00163 node->right = clean_NOT_intree(node->right);
00164 if (node->left == NULL && node->right == NULL)
00165 {
00166 pfree(node);
00167 res = NULL;
00168 }
00169 else if (node->left == NULL)
00170 {
00171 res = node->right;
00172 pfree(node);
00173 }
00174 else if (node->right == NULL)
00175 {
00176 res = node->left;
00177 pfree(node);
00178 }
00179 return res;
00180 }
00181 return node;
00182 }
00183
00184 QueryItem *
00185 clean_NOT(QueryItem *ptr, int *len)
00186 {
00187 NODE *root = maketree(ptr);
00188
00189 return plaintree(clean_NOT_intree(root), len);
00190 }
00191
00192
00193 #ifdef V_UNKNOWN
00194 #undef V_UNKNOWN
00195 #endif
00196 #ifdef V_FALSE
00197 #undef V_FALSE
00198 #endif
00199
00200
00201
00202
00203 #define V_UNKNOWN 0
00204
00205 #define V_TRUE 1
00206
00207 #define V_FALSE 2
00208
00209 #define V_STOP 3
00210
00211
00212
00213
00214
00215 static NODE *
00216 clean_fakeval_intree(NODE *node, char *result)
00217 {
00218 char lresult = V_UNKNOWN,
00219 rresult = V_UNKNOWN;
00220
00221
00222 check_stack_depth();
00223
00224 if (node->valnode->type == QI_VAL)
00225 return node;
00226 else if (node->valnode->type == QI_VALSTOP)
00227 {
00228 pfree(node);
00229 *result = V_STOP;
00230 return NULL;
00231 }
00232
00233 Assert(node->valnode->type == QI_OPR);
00234
00235 if (node->valnode->qoperator.oper == OP_NOT)
00236 {
00237 node->right = clean_fakeval_intree(node->right, &rresult);
00238 if (!node->right)
00239 {
00240 *result = V_STOP;
00241 freetree(node);
00242 return NULL;
00243 }
00244 }
00245 else
00246 {
00247 NODE *res = node;
00248
00249 node->left = clean_fakeval_intree(node->left, &lresult);
00250 node->right = clean_fakeval_intree(node->right, &rresult);
00251
00252 if (lresult == V_STOP && rresult == V_STOP)
00253 {
00254 freetree(node);
00255 *result = V_STOP;
00256 return NULL;
00257 }
00258 else if (lresult == V_STOP)
00259 {
00260 res = node->right;
00261 pfree(node);
00262 }
00263 else if (rresult == V_STOP)
00264 {
00265 res = node->left;
00266 pfree(node);
00267 }
00268 return res;
00269 }
00270 return node;
00271 }
00272
00273 QueryItem *
00274 clean_fakeval(QueryItem *ptr, int *len)
00275 {
00276 NODE *root = maketree(ptr);
00277 char result = V_UNKNOWN;
00278 NODE *resroot;
00279
00280 resroot = clean_fakeval_intree(root, &result);
00281 if (result != V_UNKNOWN)
00282 {
00283 ereport(NOTICE,
00284 (errmsg("text-search query contains only stop words or doesn't contain lexemes, ignored")));
00285 *len = 0;
00286 return NULL;
00287 }
00288
00289 return plaintree(resroot, len);
00290 }