aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteManip.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1998-10-21 16:21:29 +0000
committerBruce Momjian <bruce@momjian.us>1998-10-21 16:21:29 +0000
commit524f4b2d1064d482ba968d46afb081563e97a653 (patch)
treeee1d14908285f79d0039e561dd13de3324b8ea33 /src/backend/rewrite/rewriteManip.c
parent858a3b570ab4e402e7b0b8f383237ad4a5d13c41 (diff)
downloadpostgresql-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.c344
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)
{