static QTNode * findeq(QTNode * node, QTNode * ex, MemoryType memtype, QTNode * subs, bool *isfind) { if ((node->sign & ex->sign) != ex->sign || node->valnode->type != ex->valnode->type || node->valnode->val != ex->valnode->val) return node; if (node->flags & QTN_NOCHANGE) return node; if (node->valnode->type == OPR) { if (node->nchild == ex->nchild) { if (QTNEq(node, ex)) { QTNFree(node); if (subs) { node = QTNCopy(subs, memtype); node->flags |= QTN_NOCHANGE; } else node = NULL; *isfind = true; } } else if (node->nchild > ex->nchild) { int *counters = (int *) palloc(sizeof(int) * node->nchild); int i; QTNode *tnode = (QTNode *) MEMALLOC(memtype, sizeof(QTNode)); memset(tnode, 0, sizeof(QTNode)); tnode->child = (QTNode **) MEMALLOC(memtype, sizeof(QTNode *) * ex->nchild); tnode->nchild = ex->nchild; tnode->valnode = (ITEM *) MEMALLOC(memtype, sizeof(ITEM)); *(tnode->valnode) = *(ex->valnode); for (i = 0; i < ex->nchild; i++) counters[i] = i; do { tnode->sign = 0; for (i = 0; i < ex->nchild; i++) { tnode->child[i] = node->child[counters[i]]; tnode->sign |= tnode->child[i]->sign; } if (QTNEq(tnode, ex)) { int j = 0; MEMFREE(memtype, tnode->valnode); MEMFREE(memtype, tnode->child); MEMFREE(memtype, tnode); if (subs) { tnode = QTNCopy(subs, memtype); tnode->flags = QTN_NOCHANGE | QTN_NEEDFREE; } else tnode = NULL; node->child[counters[0]] = tnode; for (i = 1; i < ex->nchild; i++) node->child[counters[i]] = NULL; for (i = 0; i < node->nchild; i++) { if (node->child[i]) { node->child[j] = node->child[i]; j++; } } node->nchild = j; *isfind = true; break; } } while (addone(counters, ex->nchild - 1, node->nchild)); if (tnode && (tnode->flags & QTN_NOCHANGE) == 0) { MEMFREE(memtype, tnode->valnode); MEMFREE(memtype, tnode->child); MEMFREE(memtype, tnode); } else QTNSort(node); pfree(counters); } } else if (QTNEq(node, ex)) { QTNFree(node); if (subs) { node = QTNCopy(subs, memtype); node->flags |= QTN_NOCHANGE; } else { node = NULL; } *isfind = true; } return node; }
/* * 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) return node; if (node->flags & QTN_NOCHANGE) return node; if (node->valnode->type == QI_OPR) { if (node->valnode->qoperator.oper != ex->valnode->qoperator.oper) return node; if (node->nchild == ex->nchild) { if (QTNEq(node, ex)) { QTNFree(node); if (subs) { node = QTNCopy(subs); node->flags |= QTN_NOCHANGE; } else node = NULL; *isfind = true; } } 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)); memset(tnode, 0, sizeof(QTNode)); tnode->child = (QTNode **) palloc(sizeof(QTNode *) * ex->nchild); tnode->nchild = ex->nchild; tnode->valnode = (QueryItem *) palloc(sizeof(QueryItem)); *(tnode->valnode) = *(ex->valnode); for (i = 0; i < ex->nchild; i++) counters[i] = i; do { tnode->sign = 0; for (i = 0; i < ex->nchild; i++) { tnode->child[i] = node->child[counters[i]]; tnode->sign |= tnode->child[i]->sign; } if (QTNEq(tnode, ex)) { int j = 0; pfree(tnode->valnode); pfree(tnode->child); pfree(tnode); if (subs) { tnode = QTNCopy(subs); tnode->flags = QTN_NOCHANGE | QTN_NEEDFREE; } else tnode = NULL; node->child[counters[0]] = tnode; for (i = 1; i < ex->nchild; i++) node->child[counters[i]] = NULL; for (i = 0; i < node->nchild; i++) { if (node->child[i]) { node->child[j] = node->child[i]; j++; } } node->nchild = j; *isfind = true; break; } } while (addone(counters, ex->nchild - 1, node->nchild)); if (tnode && (tnode->flags & QTN_NOCHANGE) == 0) { pfree(tnode->valnode); pfree(tnode->child); pfree(tnode); } else QTNSort(node); pfree(counters); } } else { Assert(node->valnode->type == QI_VAL); if (node->valnode->qoperand.valcrc != ex->valnode->qoperand.valcrc) return node; else if (QTNEq(node, ex)) { QTNFree(node); if (subs) { node = QTNCopy(subs); node->flags |= QTN_NOCHANGE; } else { node = NULL; } *isfind = true; } } return node; }