From 524f4b2d1064d482ba968d46afb081563e97a653 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 21 Oct 1998 16:21:29 +0000 Subject: [PATCH] The patch does 2 things: Fixes a bug in the rule system that caused a crashing backend when a join-view with calculated column is used in subselect. Modifies EXPLAIN to explain rewritten queries instead of the plain SeqScan on a view. Rules can produce very deep MORE Jan. --- src/backend/commands/explain.c | 52 ++- src/backend/commands/recipe.c | 6 +- src/backend/commands/view.c | 8 +- src/backend/rewrite/rewriteHandler.c | 523 ++++++++------------------- src/backend/rewrite/rewriteManip.c | 344 ++++++++++++------ src/include/rewrite/rewriteManip.h | 4 +- 6 files changed, 442 insertions(+), 495 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 63534050f1..1b861c9620 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.24 1998/09/01 04:27:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.25 1998/10/21 16:21:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include #include #include +#include typedef struct ExplainState { @@ -37,6 +38,8 @@ typedef struct ExplainState } ExplainState; static char *Explain_PlanToString(Plan *plan, ExplainState *es); +static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest); + /* * ExplainQuery - @@ -46,11 +49,8 @@ static char *Explain_PlanToString(Plan *plan, ExplainState *es); void ExplainQuery(Query *query, bool verbose, CommandDest dest) { - char *s = NULL, - *s2; - Plan *plan; - ExplainState *es; - int len; + List *rewritten; + List *l; if (IsAbortedTransactionBlockState()) { @@ -64,6 +64,35 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest) return; } + /* Rewrite through rule system */ + rewritten = QueryRewrite(query); + + /* In the case of an INSTEAD NOTHING, tell at least that */ + if (rewritten == NIL) + { + elog(NOTICE, "query rewrites to nothing"); + return; + } + + /* Explain every plan */ + foreach(l, rewritten) + ExplainOneQuery(lfirst(l), verbose, dest); +} + +/* + * ExplainOneQuery - + * print out the execution plan for one query + * + */ +static void +ExplainOneQuery(Query *query, bool verbose, CommandDest dest) +{ + char *s = NULL, + *s2; + Plan *plan; + ExplainState *es; + int len; + /* plan the queries (XXX we've ignored rewrite!!) */ plan = planner(query); @@ -202,8 +231,13 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) { RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable); - sprintf(buf, " on %s", rte->refname); - appendStringInfo(str, buf); + appendStringInfo(str, " on "); + if (strcmp(rte->refname, rte->relname) != 0) + { + sprintf(buf, "%s ", rte->relname); + appendStringInfo(str, buf); + } + appendStringInfo(str, rte->refname); } break; default: @@ -232,7 +266,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 4, es); + explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 2, es); } es->rtable = saved_rtable; } diff --git a/src/backend/commands/recipe.c b/src/backend/commands/recipe.c index f8b7ce15df..2d5662aa26 100644 --- a/src/backend/commands/recipe.c +++ b/src/backend/commands/recipe.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.24 1998/09/01 04:27:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.25 1998/10/21 16:21:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -350,8 +350,8 @@ tg_rewriteQuery(TgRecipe * r, * need to offset the var nodes in the qual and targetlist * because they are indexed off the original rtable */ - OffsetVarNodes((Node *) inputQ->qual, rt_length); - OffsetVarNodes((Node *) inputQ->targetList, rt_length); + OffsetVarNodes((Node *) inputQ->qual, rt_length, 0); + OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0); /* append the range tables from the children nodes */ rtable = nconc(rtable, input_rtable); diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index cf81e8be66..fc5755edd7 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.25 1998/09/01 04:28:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.26 1998/10/21 16:21:22 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -219,10 +219,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) /* * first offset all var nodes by 2 */ - OffsetVarNodes((Node *) viewParse->targetList, 2); - OffsetVarNodes(viewParse->qual, 2); + OffsetVarNodes((Node *) viewParse->targetList, 2, 0); + OffsetVarNodes(viewParse->qual, 2, 0); - OffsetVarNodes(viewParse->havingQual, 2); + OffsetVarNodes(viewParse->havingQual, 2, 0); /* diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index a0f30698ab..8eaa8dbb94 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.24 1998/10/20 17:21:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.25 1998/10/21 16:21:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -48,8 +48,6 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree, bool *instead_flag); static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up); static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up); -static void offset_varnodes(Node *node, int offset, int sublevels_up); -static void change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up); static void modifyAggregUplevel(Node *node); static void modifyAggregChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up); static void modifyAggregDropQual(Node **nodePtr, Node *orignode, Expr *expr); @@ -107,9 +105,9 @@ gatherRewriteMeta(Query *parsetree, info->rt = append(info->rt, info->rule_action->rtable); info->new_varno = PRS2_NEW_VARNO + rt_length; - OffsetVarNodes(info->rule_action->qual, rt_length); - OffsetVarNodes((Node *) info->rule_action->targetList, rt_length); - OffsetVarNodes(info->rule_qual, rt_length); + OffsetVarNodes(info->rule_action->qual, rt_length, 0); + OffsetVarNodes((Node *) info->rule_action->targetList, rt_length, 0); + OffsetVarNodes(info->rule_qual, rt_length, 0); ChangeVarNodes((Node *) info->rule_action->qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes((Node *) info->rule_action->targetList, @@ -550,364 +548,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) } -/* - * offset_varnodes - - * We need another version of OffsetVarNodes() when processing - * RIR rules - */ -static void -offset_varnodes(Node *node, int offset, int sublevels_up) -{ - if (node == NULL) - return; - - switch(nodeTag(node)) { - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - - offset_varnodes( - (Node *)(tle->expr), - offset, - sublevels_up); - } - break; - - case T_Aggreg: - { - Aggreg *agg = (Aggreg *)node; - - offset_varnodes( - (Node *)(agg->target), - offset, - sublevels_up); - } - break; - - case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - offset_varnodes( - (Node *)(grp->entry), - offset, - sublevels_up); - } - break; - - case T_Expr: - { - Expr *exp = (Expr *)node; - - offset_varnodes( - (Node *)(exp->args), - offset, - sublevels_up); - } - break; - - case T_Iter: - { - Iter *iter = (Iter *)node; - - offset_varnodes( - (Node *)(iter->iterexpr), - offset, - sublevels_up); - } - break; - - case T_ArrayRef: - { - ArrayRef *ref = (ArrayRef *)node; - - offset_varnodes( - (Node *)(ref->refupperindexpr), - offset, - sublevels_up); - offset_varnodes( - (Node *)(ref->reflowerindexpr), - offset, - sublevels_up); - offset_varnodes( - (Node *)(ref->refexpr), - offset, - sublevels_up); - offset_varnodes( - (Node *)(ref->refassgnexpr), - offset, - sublevels_up); - } - break; - - case T_Var: - { - Var *var = (Var *)node; - - if (var->varlevelsup == sublevels_up) { - var->varno += offset; - var->varnoold += offset; - } - } - break; - - case T_Param: - break; - - case T_Const: - break; - - case T_List: - { - List *l; - - foreach (l, (List *)node) - offset_varnodes( - (Node *)lfirst(l), - offset, - sublevels_up); - } - break; - - case T_SubLink: - { - SubLink *sub = (SubLink *)node; - - offset_varnodes( - (Node *)(sub->lefthand), - offset, - sublevels_up); - - offset_varnodes( - (Node *)(sub->subselect), - offset, - sublevels_up + 1); - } - break; - - case T_Query: - { - Query *qry = (Query *)node; - - offset_varnodes( - (Node *)(qry->targetList), - offset, - sublevels_up); - - offset_varnodes( - (Node *)(qry->qual), - offset, - sublevels_up); - - offset_varnodes( - (Node *)(qry->havingQual), - offset, - sublevels_up); - - offset_varnodes( - (Node *)(qry->groupClause), - offset, - sublevels_up); - } - break; - - default: - elog(NOTICE, "unknown node tag %d in offset_varnodes()", nodeTag(node)); - elog(NOTICE, "Node is: %s", nodeToString(node)); - break; - - - } -} - - -/* - * change_varnodes - - * and another ChangeVarNodes() too - */ -static void -change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up) -{ - if (node == NULL) - return; - - switch(nodeTag(node)) { - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *)node; - - change_varnodes( - (Node *)(tle->expr), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_Aggreg: - { - Aggreg *agg = (Aggreg *)node; - - change_varnodes( - (Node *)(agg->target), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_GroupClause: - { - GroupClause *grp = (GroupClause *)node; - - change_varnodes( - (Node *)(grp->entry), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_Expr: - { - Expr *exp = (Expr *)node; - - change_varnodes( - (Node *)(exp->args), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_Iter: - { - Iter *iter = (Iter *)node; - - change_varnodes( - (Node *)(iter->iterexpr), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_ArrayRef: - { - ArrayRef *ref = (ArrayRef *)node; - - change_varnodes( - (Node *)(ref->refupperindexpr), - rt_index, - new_index, - sublevels_up); - change_varnodes( - (Node *)(ref->reflowerindexpr), - rt_index, - new_index, - sublevels_up); - change_varnodes( - (Node *)(ref->refexpr), - rt_index, - new_index, - sublevels_up); - change_varnodes( - (Node *)(ref->refassgnexpr), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_Var: - { - Var *var = (Var *)node; - - if (var->varlevelsup == sublevels_up && - var->varno == rt_index) { - var->varno = new_index; - var->varnoold = new_index; - } - } - break; - - case T_Param: - break; - - case T_Const: - break; - - case T_List: - { - List *l; - - foreach (l, (List *)node) - change_varnodes( - (Node *)lfirst(l), - rt_index, - new_index, - sublevels_up); - } - break; - - case T_SubLink: - { - SubLink *sub = (SubLink *)node; - - change_varnodes( - (Node *)(sub->lefthand), - rt_index, - new_index, - sublevels_up); - - change_varnodes( - (Node *)(sub->subselect), - rt_index, - new_index, - sublevels_up + 1); - } - break; - - case T_Query: - { - Query *qry = (Query *)node; - - change_varnodes( - (Node *)(qry->targetList), - rt_index, - new_index, - sublevels_up); - - change_varnodes( - (Node *)(qry->qual), - rt_index, - new_index, - sublevels_up); - - change_varnodes( - (Node *)(qry->havingQual), - rt_index, - new_index, - sublevels_up); - - change_varnodes( - (Node *)(qry->groupClause), - rt_index, - new_index, - sublevels_up); - } - break; - - default: - elog(NOTICE, "unknown node tag %d in change_varnodes()", nodeTag(node)); - elog(NOTICE, "Node is: %s", nodeToString(node)); - break; - - - } -} - - /* * modifyAggregUplevel - * In the newly created sublink for an aggregate column used in @@ -1655,6 +1295,121 @@ make_null(Oid type) } +static void +apply_RIR_adjust_sublevel(Node *node, int sublevels_up) +{ + if (node == NULL) + return; + + switch(nodeTag(node)) { + case T_TargetEntry: + { + TargetEntry *tle = (TargetEntry *)node; + + apply_RIR_adjust_sublevel( + (Node *)(tle->expr), + sublevels_up); + } + break; + + case T_Aggreg: + { + Aggreg *agg = (Aggreg *)node; + + apply_RIR_adjust_sublevel( + (Node *)(agg->target), + sublevels_up); + } + break; + + case T_GroupClause: + { + GroupClause *grp = (GroupClause *)node; + + apply_RIR_adjust_sublevel( + (Node *)(grp->entry), + sublevels_up); + } + break; + + case T_Expr: + { + Expr *exp = (Expr *)node; + + apply_RIR_adjust_sublevel( + (Node *)(exp->args), + sublevels_up); + } + break; + + case T_Iter: + { + Iter *iter = (Iter *)node; + + apply_RIR_adjust_sublevel( + (Node *)(iter->iterexpr), + sublevels_up); + } + break; + + case T_ArrayRef: + { + ArrayRef *ref = (ArrayRef *)node; + + apply_RIR_adjust_sublevel( + (Node *)(ref->refupperindexpr), + sublevels_up); + + apply_RIR_adjust_sublevel( + (Node *)(ref->reflowerindexpr), + sublevels_up); + + apply_RIR_adjust_sublevel( + (Node *)(ref->refexpr), + sublevels_up); + + apply_RIR_adjust_sublevel( + (Node *)(ref->refassgnexpr), + sublevels_up); + } + break; + + case T_Var: + { + Var *var = (Var *)node; + + var->varlevelsup = sublevels_up; + } + break; + + case T_Param: + break; + + case T_Const: + break; + + case T_List: + { + List *l; + + foreach (l, (List *)node) { + apply_RIR_adjust_sublevel( + (Node *)lfirst(l), + sublevels_up); + } + } + break; + + default: + elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node)); + elog(NOTICE, "Node is: %s", nodeToString(node)); + break; + + + } +} + + static void apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up) { @@ -1790,10 +1545,8 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in } exp = copyObject(exp); - if (var->varlevelsup > 0 && - nodeTag(exp) == T_Var) { - ((Var *)exp)->varlevelsup = var->varlevelsup; - } + if (var->varlevelsup > 0) + apply_RIR_adjust_sublevel(exp, var->varlevelsup); *nodePtr = exp; *modified = TRUE; } @@ -1885,8 +1638,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); break; - - } } @@ -1938,12 +1689,12 @@ ApplyRetrieveRule(Query *parsetree, parsetree->rtable = rtable; rule_action->rtable = rtable; - offset_varnodes((Node *) rule_qual, rt_length, 0); - offset_varnodes((Node *) rule_action, rt_length, 0); + OffsetVarNodes((Node *) rule_qual, rt_length, 0); + OffsetVarNodes((Node *) rule_action, rt_length, 0); - change_varnodes((Node *) rule_qual, + ChangeVarNodes((Node *) rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); - change_varnodes((Node *) rule_action, + ChangeVarNodes((Node *) rule_action, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); if (relation_level) @@ -2246,7 +1997,7 @@ CopyAndAddQual(Query *parsetree, rt_length = length(rtable); rtable = append(rtable, listCopy(rule_action->rtable)); new_tree->rtable = rtable; - OffsetVarNodes(new_qual, rt_length); + OffsetVarNodes(new_qual, rt_length, 0); ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); } /* XXX -- where current doesn't work for instead nothing.... yet */ @@ -2385,6 +2136,28 @@ fireRules(Query *parsetree, if (rule_action->commandType == CMD_NOTHING) continue; + /*-------------------------------------------------- + * We copy the qualifications of the parsetree + * to the action and vice versa. So force + * hasSubLinks if one of them has it. + * + * As of 6.4 only parsetree qualifications can + * have sublinks. If this changes, we must make + * this a node lookup at the end of rewriting. + * + * Jan + *-------------------------------------------------- + */ + if (parsetree->hasSubLinks && !rule_action->hasSubLinks) + { + rule_action = copyObject(rule_action); + rule_action->hasSubLinks = TRUE; + } + if (!parsetree->hasSubLinks && rule_action->hasSubLinks) + { + parsetree->hasSubLinks = TRUE; + } + /*-------------------------------------------------- * Step 1: * Rewrite current.attribute or current to tuple variable diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index d589943dc5..64da8479d1 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.21 1998/10/20 17:21:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.22 1998/10/21 16:21:26 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -32,222 +32,362 @@ static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node, int sublevels_up); - +/* + * OffsetVarnodes - + */ void -OffsetVarNodes(Node *node, int offset) +OffsetVarNodes(Node *node, int offset, int sublevels_up) { if (node == NULL) return; - switch (nodeTag(node)) - { + + switch(nodeTag(node)) { case T_TargetEntry: { - TargetEntry *tle = (TargetEntry *) node; + TargetEntry *tle = (TargetEntry *)node; - OffsetVarNodes(tle->expr, offset); + OffsetVarNodes( + (Node *)(tle->expr), + offset, + sublevels_up); } break; + case T_Aggreg: { - Aggreg *agg = (Aggreg *) node; + Aggreg *agg = (Aggreg *)node; - OffsetVarNodes(agg->target, offset); + OffsetVarNodes( + (Node *)(agg->target), + offset, + sublevels_up); } break; - /* - * This has to be done to make queries using groupclauses work - * on views - */ case T_GroupClause: { - GroupClause *group = (GroupClause *) node; + GroupClause *grp = (GroupClause *)node; - OffsetVarNodes((Node *) (group->entry), offset); + OffsetVarNodes( + (Node *)(grp->entry), + offset, + sublevels_up); } break; + case T_Expr: { - Expr *expr = (Expr *) node; + Expr *exp = (Expr *)node; - OffsetVarNodes((Node *) expr->args, offset); + OffsetVarNodes( + (Node *)(exp->args), + offset, + sublevels_up); } break; + case T_Iter: { - Iter *iter = (Iter *) node; + Iter *iter = (Iter *)node; - OffsetVarNodes((Node *) iter->iterexpr, offset); + OffsetVarNodes( + (Node *)(iter->iterexpr), + offset, + sublevels_up); } break; + case T_ArrayRef: { - ArrayRef *ref = (ArrayRef *) node; + ArrayRef *ref = (ArrayRef *)node; - OffsetVarNodes((Node *) ref->refupperindexpr, offset); - OffsetVarNodes((Node *) ref->reflowerindexpr, offset); - OffsetVarNodes((Node *) ref->refexpr, offset); - OffsetVarNodes((Node *) ref->refassgnexpr, offset); + OffsetVarNodes( + (Node *)(ref->refupperindexpr), + offset, + sublevels_up); + OffsetVarNodes( + (Node *)(ref->reflowerindexpr), + offset, + sublevels_up); + OffsetVarNodes( + (Node *)(ref->refexpr), + offset, + sublevels_up); + OffsetVarNodes( + (Node *)(ref->refassgnexpr), + offset, + sublevels_up); } break; + case T_Var: { - Var *var = (Var *) node; + Var *var = (Var *)node; - var->varno += offset; - var->varnoold += offset; + if (var->varlevelsup == sublevels_up) { + var->varno += offset; + var->varnoold += offset; + } } break; + + case T_Param: + break; + + case T_Const: + break; + case T_List: { - List *l; + List *l; - foreach(l, (List *) node) - OffsetVarNodes(lfirst(l), offset); + foreach (l, (List *)node) + OffsetVarNodes( + (Node *)lfirst(l), + offset, + sublevels_up); } break; + case T_SubLink: { - SubLink *sublink = (SubLink *) node; + SubLink *sub = (SubLink *)node; - /* - * We also have to adapt the variables used in - * sublink->lefthand and sublink->oper - */ - OffsetVarNodes((Node *) (sublink->lefthand), offset); + OffsetVarNodes( + (Node *)(sub->lefthand), + offset, + sublevels_up); - /* - * Make sure the first argument of sublink->oper points to - * the same var as sublink->lefthand does otherwise we - * will run into troubles using aggregates (aggno will not - * be set correctly) - */ - lfirst(((Expr *) lfirst(sublink->oper))->args) = - lfirst(sublink->lefthand); + OffsetVarNodes( + (Node *)(sub->subselect), + offset, + sublevels_up + 1); } break; + + case T_Query: + { + Query *qry = (Query *)node; + + OffsetVarNodes( + (Node *)(qry->targetList), + offset, + sublevels_up); + + OffsetVarNodes( + (Node *)(qry->qual), + offset, + sublevels_up); + + OffsetVarNodes( + (Node *)(qry->havingQual), + offset, + sublevels_up); + + OffsetVarNodes( + (Node *)(qry->groupClause), + offset, + sublevels_up); + } + break; + default: - /* ignore the others */ + elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node)); + elog(NOTICE, "Node is: %s", nodeToString(node)); break; + + } } + +/* + * ChangeVarNodes - + */ void -ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up) +ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) { if (node == NULL) return; - switch (nodeTag(node)) - { + + switch(nodeTag(node)) { case T_TargetEntry: { - TargetEntry *tle = (TargetEntry *) node; + TargetEntry *tle = (TargetEntry *)node; - ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up); + ChangeVarNodes( + (Node *)(tle->expr), + rt_index, + new_index, + sublevels_up); } break; + case T_Aggreg: { - Aggreg *agg = (Aggreg *) node; + Aggreg *agg = (Aggreg *)node; - ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up); + ChangeVarNodes( + (Node *)(agg->target), + rt_index, + new_index, + sublevels_up); } break; - /* - * This has to be done to make queries using groupclauses work - * on views - */ case T_GroupClause: { - GroupClause *group = (GroupClause *) node; + GroupClause *grp = (GroupClause *)node; - ChangeVarNodes((Node *) (group->entry), old_varno, new_varno, - sublevels_up); + ChangeVarNodes( + (Node *)(grp->entry), + rt_index, + new_index, + sublevels_up); } break; case T_Expr: { - Expr *expr = (Expr *) node; + Expr *exp = (Expr *)node; - ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up); + ChangeVarNodes( + (Node *)(exp->args), + rt_index, + new_index, + sublevels_up); } break; + case T_Iter: { - Iter *iter = (Iter *) node; + Iter *iter = (Iter *)node; - ChangeVarNodes((Node *) iter->iterexpr, old_varno, new_varno, sublevels_up); + ChangeVarNodes( + (Node *)(iter->iterexpr), + rt_index, + new_index, + sublevels_up); } break; + case T_ArrayRef: { - ArrayRef *ref = (ArrayRef *) node; - - ChangeVarNodes((Node *) ref->refupperindexpr, old_varno, new_varno, sublevels_up); - ChangeVarNodes((Node *) ref->reflowerindexpr, old_varno, new_varno, sublevels_up); - ChangeVarNodes((Node *) ref->refexpr, old_varno, new_varno, sublevels_up); - ChangeVarNodes((Node *) ref->refassgnexpr, old_varno, new_varno, sublevels_up); + ArrayRef *ref = (ArrayRef *)node; + + ChangeVarNodes( + (Node *)(ref->refupperindexpr), + rt_index, + new_index, + sublevels_up); + ChangeVarNodes( + (Node *)(ref->reflowerindexpr), + rt_index, + new_index, + sublevels_up); + ChangeVarNodes( + (Node *)(ref->refexpr), + rt_index, + new_index, + sublevels_up); + ChangeVarNodes( + (Node *)(ref->refassgnexpr), + rt_index, + new_index, + sublevels_up); } break; + case T_Var: { - Var *var = (Var *) node; + Var *var = (Var *)node; - if (var->varno == old_varno && - var->varlevelsup == sublevels_up) - { - var->varno = new_varno; - var->varnoold = new_varno; + if (var->varlevelsup == sublevels_up && + var->varno == rt_index) { + var->varno = new_index; + var->varnoold = new_index; } - if (var->varlevelsup > 0) - OffsetVarNodes((Node *) var, 3); - } break; + + case T_Param: + break; + + case T_Const: + break; + case T_List: { - List *l; + List *l; - foreach(l, (List *) node) - ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up); + foreach (l, (List *)node) + ChangeVarNodes( + (Node *)lfirst(l), + rt_index, + new_index, + sublevels_up); } break; + case T_SubLink: { - SubLink *sublink = (SubLink *) node; - Query *query = (Query *) sublink->subselect; + SubLink *sub = (SubLink *)node; - ChangeVarNodes((Node *) query->qual, old_varno, new_varno, - sublevels_up + 1); + ChangeVarNodes( + (Node *)(sub->lefthand), + rt_index, + new_index, + sublevels_up); - /* - * We also have to adapt the variables used in - * sublink->lefthand and sublink->oper - */ - ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno, - sublevels_up); + ChangeVarNodes( + (Node *)(sub->subselect), + rt_index, + new_index, + sublevels_up + 1); + } + break; - /* - * Make sure the first argument of sublink->oper points to - * the same var as sublink->lefthand does otherwise we - * will run into troubles using aggregates (aggno will not - * be set correctly - */ + case T_Query: + { + Query *qry = (Query *)node; - /* - * lfirst(((Expr *) lfirst(sublink->oper))->args) = - * lfirst(sublink->lefthand); - */ + ChangeVarNodes( + (Node *)(qry->targetList), + rt_index, + new_index, + sublevels_up); + + ChangeVarNodes( + (Node *)(qry->qual), + rt_index, + new_index, + sublevels_up); + + ChangeVarNodes( + (Node *)(qry->havingQual), + rt_index, + new_index, + sublevels_up); + + ChangeVarNodes( + (Node *)(qry->groupClause), + rt_index, + new_index, + sublevels_up); } break; + default: - /* ignore the others */ + elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node)); + elog(NOTICE, "Node is: %s", nodeToString(node)); break; + + } } + + void AddQual(Query *parsetree, Node *qual) { diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 7924f93161..e1b54829bb 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.10 1998/10/08 18:30:41 momjian Exp $ + * $Id: rewriteManip.h,v 1.11 1998/10/21 16:21:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,7 @@ #include "rewrite/rewriteHandler.h" /* RewriteManip.c */ -void OffsetVarNodes(Node *node, int offset); +void OffsetVarNodes(Node *node, int offset, int sublevels_up); void ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up); void AddQual(Query *parsetree, Node *qual); -- 2.40.0