diff options
author | Bruce Momjian <bruce@momjian.us> | 1998-01-21 04:24:46 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1998-01-21 04:24:46 +0000 |
commit | 0f413d2dc20111d7d539e2c3eee8ce0ef441ca36 (patch) | |
tree | 6a94e75b1fb8b214fe6cbb16385355856c8deb67 /src/backend/rewrite/rewriteHandler.c | |
parent | 7e46348e6219f7b827fd315140437a8abfa0226f (diff) | |
download | postgresql-0f413d2dc20111d7d539e2c3eee8ce0ef441ca36.tar.gz postgresql-0f413d2dc20111d7d539e2c3eee8ce0ef441ca36.zip |
Make subqueries rewrite properly.
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 68f34e6cd5d..415ce6e80f8 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.10 1998/01/09 05:48:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.11 1998/01/21 04:24:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,12 +29,12 @@ #include "commands/creatinh.h" #include "access/heapam.h" -static void -ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, +static void ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, int rt_index, int relation_level, int *modified); -static List * -fireRules(Query *parsetree, int rt_index, CmdType event, +static List *fireRules(Query *parsetree, int rt_index, CmdType event, bool *instead_flag, List *locks, List **qual_products); +static void QueryRewriteSubLink(Node *node); +static List *QueryRewriteOne(Query *parsetree); static List *deepRewriteQuery(Query *parsetree); /* @@ -77,11 +77,11 @@ gatherRewriteMeta(Query *parsetree, OffsetVarNodes((Node *) info->rule_action->targetList, rt_length); OffsetVarNodes(info->rule_qual, rt_length); ChangeVarNodes((Node *) info->rule_action->qual, - PRS2_CURRENT_VARNO + rt_length, rt_index); + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes((Node *) info->rule_action->targetList, - PRS2_CURRENT_VARNO + rt_length, rt_index); + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes(info->rule_qual, - PRS2_CURRENT_VARNO + rt_length, rt_index); + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); /* * bug here about replace CURRENT -- sort of replace current is @@ -292,10 +292,10 @@ ApplyRetrieveRule(Query *parsetree, OffsetVarNodes((Node *) rule_action->targetList, rt_length); OffsetVarNodes(rule_qual, rt_length); ChangeVarNodes(rule_action->qual, - PRS2_CURRENT_VARNO + rt_length, rt_index); + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes((Node *) rule_action->targetList, - PRS2_CURRENT_VARNO + rt_length, rt_index); - ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index); + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); + ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); if (relation_level) { HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index, @@ -402,7 +402,7 @@ CopyAndAddQual(Query *parsetree, rtable = append(rtable, listCopy(rule_action->rtable)); new_tree->rtable = rtable; OffsetVarNodes(new_qual, rt_length); - ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index); + ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); } /* XXX -- where current doesn't work for instead nothing.... yet */ AddNotQual(new_tree, new_qual); @@ -628,6 +628,82 @@ static int numQueryRewriteInvoked = 0; List * QueryRewrite(Query *parsetree) { + + QueryRewriteSubLink(parsetree->qual); + return QueryRewriteOne(parsetree); +} + +/* + * QueryRewriteSubLink + * + * This rewrites the SubLink subqueries first, doing the lowest ones first. + * We already have code in the main rewrite loops to process correlated + * variables from upper queries that exist in subqueries. + */ +static void +QueryRewriteSubLink(Node *node) +{ + if (node == NULL) + return; + + switch (nodeTag(node)) + { + case T_TargetEntry: + break; + case T_Aggreg: + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + QueryRewriteSubLink((Node *)expr->args); + } + break; + case T_Var: + break; + case T_List: + { + List *l; + + foreach(l, (List *) node) + QueryRewriteSubLink(lfirst(l)); + } + break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + List *ret; + + /* + * Nest down first. We do this so if a rewrite adds a + * SubLink we don't process it as part of this loop. + */ + QueryRewriteSubLink((Node *)query->qual); + + ret = QueryRewriteOne(query); + if (!ret) + sublink->subselect = NULL; + else if (lnext(ret) == NIL) + sublink->subselect = lfirst(ret); + else + elog(ERROR,"Don't know how to process subquery that rewrites to multiple queries."); + } + break; + default: + /* ignore the others */ + break; + } + return; +} + +/* + * QueryOneRewrite - + * rewrite one query + */ +static List * +QueryRewriteOne(Query *parsetree) +{ numQueryRewriteInvoked = 0; /* |