00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "tsearch/ts_utils.h"
00018 #include "miscadmin.h"
00019
00020 QTNode *
00021 QT2QTN(QueryItem *in, char *operand)
00022 {
00023 QTNode *node = (QTNode *) palloc0(sizeof(QTNode));
00024
00025
00026 check_stack_depth();
00027
00028 node->valnode = in;
00029
00030 if (in->type == QI_OPR)
00031 {
00032 node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
00033 node->child[0] = QT2QTN(in + 1, operand);
00034 node->sign = node->child[0]->sign;
00035 if (in->qoperator.oper == OP_NOT)
00036 node->nchild = 1;
00037 else
00038 {
00039 node->nchild = 2;
00040 node->child[1] = QT2QTN(in + in->qoperator.left, operand);
00041 node->sign |= node->child[1]->sign;
00042 }
00043 }
00044 else if (operand)
00045 {
00046 node->word = operand + in->qoperand.distance;
00047 node->sign = ((uint32) 1) << (((unsigned int) in->qoperand.valcrc) % 32);
00048 }
00049
00050 return node;
00051 }
00052
00053 void
00054 QTNFree(QTNode *in)
00055 {
00056 if (!in)
00057 return;
00058
00059
00060 check_stack_depth();
00061
00062 if (in->valnode->type == QI_VAL && in->word && (in->flags & QTN_WORDFREE) != 0)
00063 pfree(in->word);
00064
00065 if (in->child)
00066 {
00067 if (in->valnode)
00068 {
00069 if (in->valnode->type == QI_OPR && in->nchild > 0)
00070 {
00071 int i;
00072
00073 for (i = 0; i < in->nchild; i++)
00074 QTNFree(in->child[i]);
00075 }
00076 if (in->flags & QTN_NEEDFREE)
00077 pfree(in->valnode);
00078 }
00079 pfree(in->child);
00080 }
00081
00082 pfree(in);
00083 }
00084
00085 int
00086 QTNodeCompare(QTNode *an, QTNode *bn)
00087 {
00088
00089 check_stack_depth();
00090
00091 if (an->valnode->type != bn->valnode->type)
00092 return (an->valnode->type > bn->valnode->type) ? -1 : 1;
00093
00094 if (an->valnode->type == QI_OPR)
00095 {
00096 QueryOperator *ao = &an->valnode->qoperator;
00097 QueryOperator *bo = &bn->valnode->qoperator;
00098
00099 if (ao->oper != bo->oper)
00100 return (ao->oper > bo->oper) ? -1 : 1;
00101
00102 if (an->nchild != bn->nchild)
00103 return (an->nchild > bn->nchild) ? -1 : 1;
00104
00105 {
00106 int i,
00107 res;
00108
00109 for (i = 0; i < an->nchild; i++)
00110 if ((res = QTNodeCompare(an->child[i], bn->child[i])) != 0)
00111 return res;
00112 }
00113 return 0;
00114 }
00115 else if (an->valnode->type == QI_VAL)
00116 {
00117 QueryOperand *ao = &an->valnode->qoperand;
00118 QueryOperand *bo = &bn->valnode->qoperand;
00119
00120 if (ao->valcrc != bo->valcrc)
00121 {
00122 return (ao->valcrc > bo->valcrc) ? -1 : 1;
00123 }
00124
00125 return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
00126 }
00127 else
00128 {
00129 elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
00130 return 0;
00131 }
00132 }
00133
00134 static int
00135 cmpQTN(const void *a, const void *b)
00136 {
00137 return QTNodeCompare(*(QTNode *const *) a, *(QTNode *const *) b);
00138 }
00139
00140 void
00141 QTNSort(QTNode *in)
00142 {
00143 int i;
00144
00145
00146 check_stack_depth();
00147
00148 if (in->valnode->type != QI_OPR)
00149 return;
00150
00151 for (i = 0; i < in->nchild; i++)
00152 QTNSort(in->child[i]);
00153 if (in->nchild > 1)
00154 qsort((void *) in->child, in->nchild, sizeof(QTNode *), cmpQTN);
00155 }
00156
00157 bool
00158 QTNEq(QTNode *a, QTNode *b)
00159 {
00160 uint32 sign = a->sign & b->sign;
00161
00162 if (!(sign == a->sign && sign == b->sign))
00163 return 0;
00164
00165 return (QTNodeCompare(a, b) == 0) ? true : false;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175 void
00176 QTNTernary(QTNode *in)
00177 {
00178 int i;
00179
00180
00181 check_stack_depth();
00182
00183 if (in->valnode->type != QI_OPR)
00184 return;
00185
00186 for (i = 0; i < in->nchild; i++)
00187 QTNTernary(in->child[i]);
00188
00189 for (i = 0; i < in->nchild; i++)
00190 {
00191 QTNode *cc = in->child[i];
00192
00193 if (cc->valnode->type == QI_OPR && in->valnode->qoperator.oper == cc->valnode->qoperator.oper)
00194 {
00195 int oldnchild = in->nchild;
00196
00197 in->nchild += cc->nchild - 1;
00198 in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));
00199
00200 if (i + 1 != oldnchild)
00201 memmove(in->child + i + cc->nchild, in->child + i + 1,
00202 (oldnchild - i - 1) * sizeof(QTNode *));
00203
00204 memcpy(in->child + i, cc->child, cc->nchild * sizeof(QTNode *));
00205 i += cc->nchild - 1;
00206
00207 if (cc->flags & QTN_NEEDFREE)
00208 pfree(cc->valnode);
00209 pfree(cc);
00210 }
00211 }
00212 }
00213
00214
00215
00216
00217
00218 void
00219 QTNBinary(QTNode *in)
00220 {
00221 int i;
00222
00223
00224 check_stack_depth();
00225
00226 if (in->valnode->type != QI_OPR)
00227 return;
00228
00229 for (i = 0; i < in->nchild; i++)
00230 QTNBinary(in->child[i]);
00231
00232 if (in->nchild <= 2)
00233 return;
00234
00235 while (in->nchild > 2)
00236 {
00237 QTNode *nn = (QTNode *) palloc0(sizeof(QTNode));
00238
00239 nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
00240 nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
00241
00242 nn->nchild = 2;
00243 nn->flags = QTN_NEEDFREE;
00244
00245 nn->child[0] = in->child[0];
00246 nn->child[1] = in->child[1];
00247 nn->sign = nn->child[0]->sign | nn->child[1]->sign;
00248
00249 nn->valnode->type = in->valnode->type;
00250 nn->valnode->qoperator.oper = in->valnode->qoperator.oper;
00251
00252 in->child[0] = nn;
00253 in->child[1] = in->child[in->nchild - 1];
00254 in->nchild--;
00255 }
00256 }
00257
00258
00259
00260
00261
00262 static void
00263 cntsize(QTNode *in, int *sumlen, int *nnode)
00264 {
00265
00266 check_stack_depth();
00267
00268 *nnode += 1;
00269 if (in->valnode->type == QI_OPR)
00270 {
00271 int i;
00272
00273 for (i = 0; i < in->nchild; i++)
00274 cntsize(in->child[i], sumlen, nnode);
00275 }
00276 else
00277 {
00278 *sumlen += in->valnode->qoperand.length + 1;
00279 }
00280 }
00281
00282 typedef struct
00283 {
00284 QueryItem *curitem;
00285 char *operand;
00286 char *curoperand;
00287 } QTN2QTState;
00288
00289 static void
00290 fillQT(QTN2QTState *state, QTNode *in)
00291 {
00292
00293 check_stack_depth();
00294
00295 if (in->valnode->type == QI_VAL)
00296 {
00297 memcpy(state->curitem, in->valnode, sizeof(QueryOperand));
00298
00299 memcpy(state->curoperand, in->word, in->valnode->qoperand.length);
00300 state->curitem->qoperand.distance = state->curoperand - state->operand;
00301 state->curoperand[in->valnode->qoperand.length] = '\0';
00302 state->curoperand += in->valnode->qoperand.length + 1;
00303 state->curitem++;
00304 }
00305 else
00306 {
00307 QueryItem *curitem = state->curitem;
00308
00309 Assert(in->valnode->type == QI_OPR);
00310
00311 memcpy(state->curitem, in->valnode, sizeof(QueryOperator));
00312
00313 Assert(in->nchild <= 2);
00314 state->curitem++;
00315
00316 fillQT(state, in->child[0]);
00317
00318 if (in->nchild == 2)
00319 {
00320 curitem->qoperator.left = state->curitem - curitem;
00321 fillQT(state, in->child[1]);
00322 }
00323 }
00324 }
00325
00326 TSQuery
00327 QTN2QT(QTNode *in)
00328 {
00329 TSQuery out;
00330 int len;
00331 int sumlen = 0,
00332 nnode = 0;
00333 QTN2QTState state;
00334
00335 cntsize(in, &sumlen, &nnode);
00336 len = COMPUTESIZE(nnode, sumlen);
00337
00338 out = (TSQuery) palloc0(len);
00339 SET_VARSIZE(out, len);
00340 out->size = nnode;
00341
00342 state.curitem = GETQUERY(out);
00343 state.operand = state.curoperand = GETOPERAND(out);
00344
00345 fillQT(&state, in);
00346 return out;
00347 }
00348
00349 QTNode *
00350 QTNCopy(QTNode *in)
00351 {
00352 QTNode *out;
00353
00354
00355 check_stack_depth();
00356
00357 out = (QTNode *) palloc(sizeof(QTNode));
00358
00359 *out = *in;
00360 out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
00361 *(out->valnode) = *(in->valnode);
00362 out->flags |= QTN_NEEDFREE;
00363
00364 if (in->valnode->type == QI_VAL)
00365 {
00366 out->word = palloc(in->valnode->qoperand.length + 1);
00367 memcpy(out->word, in->word, in->valnode->qoperand.length);
00368 out->word[in->valnode->qoperand.length] = '\0';
00369 out->flags |= QTN_WORDFREE;
00370 }
00371 else
00372 {
00373 int i;
00374
00375 out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);
00376
00377 for (i = 0; i < in->nchild; i++)
00378 out->child[i] = QTNCopy(in->child[i]);
00379 }
00380
00381 return out;
00382 }
00383
00384 void
00385 QTNClearFlags(QTNode *in, uint32 flags)
00386 {
00387
00388 check_stack_depth();
00389
00390 in->flags &= ~flags;
00391
00392 if (in->valnode->type != QI_VAL)
00393 {
00394 int i;
00395
00396 for (i = 0; i < in->nchild; i++)
00397 QTNClearFlags(in->child[i], flags);
00398 }
00399 }