From 0f413d2dc20111d7d539e2c3eee8ce0ef441ca36 Mon Sep 17 00:00:00 2001 From: Bruce Momjian <bruce@momjian.us> Date: Wed, 21 Jan 1998 04:24:46 +0000 Subject: [PATCH] Make subqueries rewrite properly. --- src/backend/rewrite/locks.c | 33 +++-- src/backend/rewrite/rewriteHandler.c | 100 +++++++++++-- src/backend/rewrite/rewriteManip.c | 205 ++++++++++++++++----------- src/include/rewrite/rewriteManip.h | 5 +- 4 files changed, 237 insertions(+), 106 deletions(-) diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c index b0557b042e1..56bd8e053b7 100644 --- a/src/backend/rewrite/locks.c +++ b/src/backend/rewrite/locks.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.7 1998/01/15 19:00:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.8 1998/01/21 04:24:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,8 @@ * otherwise, we return false */ static bool -nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum) +nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum, + int sublevels_up) { if (node == NULL) return FALSE; @@ -46,24 +47,24 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum) { Expr *expr = (Expr *) node; - return - nodeThisLockWasTriggered((Node *) expr->args, varno, attnum); + return nodeThisLockWasTriggered((Node *) expr->args, varno, + attnum, sublevels_up); } break; case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; - return - nodeThisLockWasTriggered(tle->expr, varno, attnum); + return nodeThisLockWasTriggered(tle->expr, varno, attnum, + sublevels_up); } break; case T_Aggreg: { Aggreg *agg = (Aggreg *) node; - return - nodeThisLockWasTriggered(agg->target, varno, attnum); + return nodeThisLockWasTriggered(agg->target, varno, attnum, + sublevels_up); } break; case T_List: @@ -72,12 +73,22 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum) foreach(l, (List *) node) { - if (nodeThisLockWasTriggered(lfirst(l), varno, attnum)) + if (nodeThisLockWasTriggered(lfirst(l), varno, attnum, + sublevels_up)) return TRUE; } return FALSE; } break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + + return nodeThisLockWasTriggered(query->qual, varno, attnum, + sublevels_up + 1); + } + break; default: break; } @@ -96,10 +107,10 @@ thisLockWasTriggered(int varno, Query *parsetree) { - if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum)) + if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0)) return true; - if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum)) + if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0)) return true; return false; 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); @@ -627,6 +627,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; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index cd5f5e16a4d..493e0c4c4ae 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.10 1998/01/15 19:00:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.11 1998/01/21 04:24:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,8 @@ #include "nodes/plannodes.h" #include "optimizer/clauses.h" -static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node); +static void ResolveNew(RewriteInfo *info, List *targetlist, + Node **node, int sublevels_up); @@ -85,7 +86,7 @@ OffsetVarNodes(Node *node, int offset) } void -ChangeVarNodes(Node *node, int old_varno, int new_varno) +ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up) { if (node == NULL) return; @@ -95,28 +96,29 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno) { TargetEntry *tle = (TargetEntry *) node; - ChangeVarNodes(tle->expr, old_varno, new_varno); + ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up); } break; case T_Aggreg: { Aggreg *agg = (Aggreg *) node; - ChangeVarNodes(agg->target, old_varno, new_varno); + ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up); } break; case T_Expr: { Expr *expr = (Expr *) node; - ChangeVarNodes((Node *) expr->args, old_varno, new_varno); + ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up); } break; case T_Var: { Var *var = (Var *) node; - if (var->varno == old_varno) + if (var->varno == old_varno && + var->varlevelsup == sublevels_up) { var->varno = new_varno; var->varnoold = new_varno; @@ -128,9 +130,16 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno) List *l; foreach(l, (List *) node) - { - ChangeVarNodes(lfirst(l), old_varno, new_varno); - } + ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up); + } + break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + + ChangeVarNodes((Node *)query->qual, old_varno, new_varno, + sublevels_up + 1); } break; default: @@ -237,7 +246,8 @@ FindMatchingTLEntry(List *tlist, char *e_attname) } static void -ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr) +ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr, + int sublevels_up) { Node *node = *nodePtr; @@ -247,20 +257,25 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr) switch (nodeTag(node)) { case T_TargetEntry: - ResolveNew(info, targetlist, &((TargetEntry *) node)->expr); + ResolveNew(info, targetlist, &((TargetEntry *) node)->expr, + sublevels_up); break; case T_Aggreg: - ResolveNew(info, targetlist, &((Aggreg *) node)->target); + ResolveNew(info, targetlist, &((Aggreg *) node)->target, + sublevels_up); break; case T_Expr: - ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args))); + ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)), + sublevels_up); break; case T_Var: { - int this_varno = (int) ((Var *) node)->varno; - Node *n; + int this_varno = (int) ((Var *) node)->varno; + int this_varlevelsup = (int) ((Var *) node)->varlevelsup; + Node *n; - if (this_varno == info->new_varno) + if (this_varno == info->new_varno && + this_varlevelsup == sublevels_up) { n = FindMatchingNew(targetlist, ((Var *) node)->varattno); @@ -288,11 +303,18 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr) List *l; foreach(l, (List *) node) - { - ResolveNew(info, targetlist, (Node **) &(lfirst(l))); - } + ResolveNew(info, targetlist, (Node **) &(lfirst(l)), + sublevels_up); break; } + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + + ResolveNew(info, targetlist, (Node **)&(query->qual), sublevels_up + 1); + } + break; default: /* ignore the others */ break; @@ -303,8 +325,8 @@ void FixNew(RewriteInfo *info, Query *parsetree) { ResolveNew(info, parsetree->targetList, - (Node **) &(info->rule_action->targetList)); - ResolveNew(info, parsetree->targetList, &info->rule_action->qual); + (Node **) &(info->rule_action->targetList), 0); + ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0); } static void @@ -314,7 +336,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr, int rt_index, int attr_num, int *modified, - int *badsql) + int *badsql, + int sublevels_up) { Node *node = *nodePtr; @@ -322,24 +345,13 @@ nodeHandleRIRAttributeRule(Node **nodePtr, return; switch (nodeTag(node)) { - case T_List: - { - List *i; - - foreach(i, (List *) node) - { - nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable, - targetlist, rt_index, attr_num, - modified, badsql); - } - } - break; case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist, - rt_index, attr_num, modified, badsql); + rt_index, attr_num, modified, badsql, + sublevels_up); } break; case T_Aggreg: @@ -347,7 +359,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr, Aggreg *agg = (Aggreg *) node; nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist, - rt_index, attr_num, modified, badsql); + rt_index, attr_num, modified, badsql, + sublevels_up); } break; case T_Expr: @@ -356,18 +369,19 @@ nodeHandleRIRAttributeRule(Node **nodePtr, nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable, targetlist, rt_index, attr_num, - modified, badsql); + modified, badsql, + sublevels_up); } break; case T_Var: { - int this_varno = (int) ((Var *) node)->varno; - NameData name_to_look_for; - - MemSet(name_to_look_for.data, 0, NAMEDATALEN); + int this_varno = ((Var *) node)->varno; + int this_varattno = ((Var *) node)->varattno; + int this_varlevelsup = ((Var *) node)->varlevelsup; if (this_varno == rt_index && - ((Var *) node)->varattno == attr_num) + this_varattno == attr_num && + this_varlevelsup == sublevels_up) { if (((Var *) node)->vartype == 32) { /* HACK */ @@ -378,29 +392,50 @@ nodeHandleRIRAttributeRule(Node **nodePtr, } else { + NameData name_to_look_for; + + name_to_look_for.data[0] = '\0'; namestrcpy(&name_to_look_for, (char *) get_attname(getrelid(this_varno, rtable), attr_num)); + if (name_to_look_for.data[0]) + { + Node *n; + + n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for); + if (n == NULL) + *nodePtr = make_null(((Var *) node)->vartype); + else + *nodePtr = n; + *modified = TRUE; + } } } - if (name_to_look_for.data[0]) - { - Node *n; + } + break; + case T_List: + { + List *i; - n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for); - if (n == NULL) - { - *nodePtr = make_null(((Var *) node)->vartype); - } - else - { - *nodePtr = n; - } - *modified = TRUE; + foreach(i, (List *) node) + { + nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable, + targetlist, rt_index, attr_num, + modified, badsql, sublevels_up); } } break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + + nodeHandleRIRAttributeRule((Node **)&(query->qual), rtable, targetlist, + rt_index, attr_num, modified, badsql, + sublevels_up + 1); + } + break; default: /* ignore the others */ break; @@ -423,9 +458,9 @@ HandleRIRAttributeRule(Query *parsetree, nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable, targetlist, rt_index, attr_num, - modified, badsql); + modified, badsql, 0); nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist, - rt_index, attr_num, modified, badsql); + rt_index, attr_num, modified, badsql, 0); } @@ -434,7 +469,8 @@ nodeHandleViewRule(Node **nodePtr, List *rtable, List *targetlist, int rt_index, - int *modified) + int *modified, + int sublevels_up) { Node *node = *nodePtr; @@ -443,24 +479,12 @@ nodeHandleViewRule(Node **nodePtr, switch (nodeTag(node)) { - case T_List: - { - List *l; - - foreach(l, (List *) node) - { - nodeHandleViewRule((Node **) (&(lfirst(l))), - rtable, targetlist, - rt_index, modified); - } - } - break; case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; nodeHandleViewRule(&(tle->expr), rtable, targetlist, - rt_index, modified); + rt_index, modified, sublevels_up); } break; case T_Aggreg: @@ -468,7 +492,7 @@ nodeHandleViewRule(Node **nodePtr, Aggreg *agg = (Aggreg *) node; nodeHandleViewRule(&(agg->target), rtable, targetlist, - rt_index, modified); + rt_index, modified, sublevels_up); } break; case T_Expr: @@ -477,33 +501,52 @@ nodeHandleViewRule(Node **nodePtr, nodeHandleViewRule((Node **) (&(expr->args)), rtable, targetlist, - rt_index, modified); + rt_index, modified, sublevels_up); } break; case T_Var: { Var *var = (Var *) node; int this_varno = var->varno; + int this_varlevelsup = var->varlevelsup; Node *n; - if (this_varno == rt_index) + if (this_varno == rt_index && + this_varlevelsup == sublevels_up) { n = FindMatchingTLEntry(targetlist, get_attname(getrelid(this_varno, rtable), var->varattno)); if (n == NULL) - { *nodePtr = make_null(((Var *) node)->vartype); - } else - { *nodePtr = n; - } *modified = TRUE; } break; } + case T_List: + { + List *l; + + foreach(l, (List *) node) + { + nodeHandleViewRule((Node **) (&(lfirst(l))), + rtable, targetlist, + rt_index, modified, sublevels_up); + } + } + break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + Query *query = (Query *)sublink->subselect; + + nodeHandleViewRule((Node **)&(query->qual), rtable, targetlist, + rt_index, modified, sublevels_up + 1); + } + break; default: /* ignore the others */ break; @@ -519,7 +562,7 @@ HandleViewRule(Query *parsetree, { nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, - modified); + modified, 0); nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist, - rt_index, modified); + rt_index, modified, 0); } diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 175cdd6ca88..c564dbf1d31 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteManip.h,v 1.5 1997/11/26 01:14:25 momjian Exp $ + * $Id: rewriteManip.h,v 1.6 1998/01/21 04:24:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,8 @@ /* RewriteManip.c */ void OffsetVarNodes(Node *node, int offset); -void ChangeVarNodes(Node *node, int old_varno, int new_varno); +void ChangeVarNodes(Node *node, int old_varno, int new_varno, + int sublevels_up); void AddQual(Query *parsetree, Node *qual); void AddNotQual(Query *parsetree, Node *qual); void FixResdomTypes(List *user_tlist); -- GitLab