diff options
author | Bruce Momjian <bruce@momjian.us> | 1998-10-21 16:21:29 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1998-10-21 16:21:29 +0000 |
commit | 524f4b2d1064d482ba968d46afb081563e97a653 (patch) | |
tree | ee1d14908285f79d0039e561dd13de3324b8ea33 /src/backend/rewrite/rewriteManip.c | |
parent | 858a3b570ab4e402e7b0b8f383237ad4a5d13c41 (diff) | |
download | postgresql-524f4b2d1064d482ba968d46afb081563e97a653.tar.gz postgresql-524f4b2d1064d482ba968d46afb081563e97a653.zip |
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.
Diffstat (limited to 'src/backend/rewrite/rewriteManip.c')
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 344 |
1 files changed, 242 insertions, 102 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index d589943dc5c..64da8479d15 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) { |