diff options
author | Teodor Sigaev <teodor@sigaev.ru> | 2007-09-07 15:09:56 +0000 |
---|---|---|
committer | Teodor Sigaev <teodor@sigaev.ru> | 2007-09-07 15:09:56 +0000 |
commit | e5be89981fc70648eedb325781cf2fbd4da05ba8 (patch) | |
tree | 8a2c587b7ae857fcbe2c2ed4ff21772c11d935a3 /src/backend/utils/adt/tsquery_rewrite.c | |
parent | da1248401d00bce0cb75fa3ab278f906f407bec9 (diff) | |
download | postgresql-e5be89981fc70648eedb325781cf2fbd4da05ba8.tar.gz postgresql-e5be89981fc70648eedb325781cf2fbd4da05ba8.zip |
Refactoring by Heikki Linnakangas <heikki@enterprisedb.com> with
small editorization by me
- Brake the QueryItem struct into QueryOperator and QueryOperand.
Type was really the only common field between them. QueryItem still
exists, and is used in the TSQuery struct as before, but it's now a
union of the two. Many other changes fell from that, like separation
of pushval_asis function into pushValue, pushOperator and pushStop.
- Moved some structs that were for internal use only from header files
to the right .c-files.
- Moved tsvector parser to a new tsvector_parser.c file. Parser code was
about half of the size of tsvector.c, it's also used from tsquery.c, and
it has some data structures of its own, so it seems better to separate
it. Cleaned up the API so that TSVectorParserState is not accessed from
outside tsvector_parser.c.
- Separated enumerations (#defines, really) used for QueryItem.type
field and as return codes from gettoken_query. It was just accidental
code sharing.
- Removed ParseQueryNode struct used internally by makepol and friends.
push*-functions now construct QueryItems directly.
- Changed int4 variables to just ints for variables like "i" or "array
size", where the storage-size was not significant.
Diffstat (limited to 'src/backend/utils/adt/tsquery_rewrite.c')
-rw-r--r-- | src/backend/utils/adt/tsquery_rewrite.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/src/backend/utils/adt/tsquery_rewrite.c b/src/backend/utils/adt/tsquery_rewrite.c index f0d22c644ae..db2fe6c53ef 100644 --- a/src/backend/utils/adt/tsquery_rewrite.c +++ b/src/backend/utils/adt/tsquery_rewrite.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.1 2007/08/21 01:11:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.2 2007/09/07 15:09:56 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -34,18 +34,26 @@ addone(int *counters, int last, int total) return 1; } +/* + * If node is equal to ex, replace it with subs. Replacement is actually done + * by returning either node or a copy of subs. + */ static QTNode * findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind) { - if ((node->sign & ex->sign) != ex->sign || node->valnode->type != ex->valnode->type || node->valnode->val != ex->valnode->val) + if ((node->sign & ex->sign) != ex->sign || + node->valnode->type != ex->valnode->type) return node; if (node->flags & QTN_NOCHANGE) return node; - - if (node->valnode->type == OPR) + + if (node->valnode->type == QI_OPR) { + if (node->valnode->operator.oper != ex->valnode->operator.oper) + return node; + if (node->nchild == ex->nchild) { if (QTNEq(node, ex)) @@ -63,6 +71,12 @@ findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind) } else if (node->nchild > ex->nchild) { + /* + * AND and NOT are commutative, so we check if a subset of the + * children match. For example, if tnode is A | B | C, and + * ex is B | C, we have a match after we convert tnode to + * A | (B | C). + */ int *counters = (int *) palloc(sizeof(int) * node->nchild); int i; QTNode *tnode = (QTNode *) palloc(sizeof(QTNode)); @@ -131,19 +145,26 @@ findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind) pfree(counters); } } - else if (QTNEq(node, ex)) + else { - QTNFree(node); - if (subs) - { - node = QTNCopy(subs); - node->flags |= QTN_NOCHANGE; - } - else + Assert(node->valnode->type == QI_VAL); + + if (node->valnode->operand.valcrc != ex->valnode->operand.valcrc) + return node; + else if (QTNEq(node, ex)) { - node = NULL; + QTNFree(node); + if (subs) + { + node = QTNCopy(subs); + node->flags |= QTN_NOCHANGE; + } + else + { + node = NULL; + } + *isfind = true; } - *isfind = true; } return node; @@ -154,7 +175,7 @@ dofindsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind) { root = findeq(root, ex, subs, isfind); - if (root && (root->flags & QTN_NOCHANGE) == 0 && root->valnode->type == OPR) + if (root && (root->flags & QTN_NOCHANGE) == 0 && root->valnode->type == QI_OPR) { int i; @@ -172,7 +193,7 @@ dropvoidsubtree(QTNode * root) if (!root) return NULL; - if (root->valnode->type == OPR) + if (root->valnode->type == QI_OPR) { int i, j = 0; @@ -188,7 +209,7 @@ dropvoidsubtree(QTNode * root) root->nchild = j; - if (root->valnode->val == (int4) '!' && root->nchild == 0) + if (root->valnode->operator.oper == OP_NOT && root->nchild == 0) { QTNFree(root); root = NULL; @@ -256,9 +277,9 @@ ts_rewrite_accum(PG_FUNCTION_ARGS) elog(ERROR, "array must be one-dimensional, not %d dimensions", ARR_NDIM(qa)); if (ArrayGetNItems(ARR_NDIM(qa), ARR_DIMS(qa)) != 3) - elog(ERROR, "array should have only three elements"); + elog(ERROR, "array must have three elements"); if (ARR_ELEMTYPE(qa) != TSQUERYOID) - elog(ERROR, "array should contain tsquery type"); + elog(ERROR, "array must contain tsquery elements"); deconstruct_array(qa, TSQUERYOID, -1, false, 'i', &elemsp, NULL, &nelemsp); @@ -499,6 +520,7 @@ tsquery_rewrite_query(PG_FUNCTION_ARGS) subs = QT2QTN(GETQUERY(subst), GETOPERAND(subst)); tree = findsubquery(tree, qex, subs, NULL); + QTNFree(qex); QTNFree(subs); |