aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-01-17 02:01:21 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-01-17 02:01:21 +0000
commita4d82dd4b4725c12a64d87967719f7690a054cbd (patch)
tree6f190e80d6fe8e4ced2593ab53407a852f4deb83 /src
parent227a404cf4badc5b245a17c674658605d8aa9397 (diff)
downloadpostgresql-a4d82dd4b4725c12a64d87967719f7690a054cbd.tar.gz
postgresql-a4d82dd4b4725c12a64d87967719f7690a054cbd.zip
Adjust API of expression_tree_mutator and query_tree_mutator to
simplify callers. It turns out the common case is that the caller does want to recurse into sub-queries, so push support for that into these subroutines.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/subselect.c10
-rw-r--r--src/backend/optimizer/prep/prepunion.c16
-rw-r--r--src/backend/optimizer/util/clauses.c101
-rw-r--r--src/backend/optimizer/util/var.c97
-rw-r--r--src/backend/rewrite/rewriteDefine.c4
-rw-r--r--src/backend/rewrite/rewriteHandler.c4
-rw-r--r--src/backend/rewrite/rewriteManip.c139
-rw-r--r--src/include/optimizer/clauses.h16
8 files changed, 167 insertions, 220 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 3c72199777e..b30454dcae2 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.66 2003/01/13 18:10:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.67 2003/01/17 02:01:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -628,12 +628,12 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
}
/*
- * Note that we will never see a SubPlan expression in the input
- * (since this is the very routine that creates 'em to begin with). So
- * the code in expression_tree_mutator() that might do inappropriate
- * things with SubPlans or SubLinks will not be exercised.
+ * We should never see a SubPlan expression in the input (since this is
+ * the very routine that creates 'em to begin with). We shouldn't find
+ * ourselves invoked directly on a Query, either.
*/
Assert(!is_subplan(node));
+ Assert(!IsA(node, Query));
/*
* If we recurse down through anything other than a List node, we are
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 4af395b860c..807364fac8d 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.86 2003/01/15 19:35:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.87 2003/01/17 02:01:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,11 +34,6 @@
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
-/* macros borrowed from expression_tree_mutator */
-
-#define FLATCOPY(newnode, node, nodetype) \
- ( (newnode) = makeNode(nodetype), \
- memcpy((newnode), (node), sizeof(nodetype)) )
typedef struct
{
@@ -765,12 +760,12 @@ adjust_inherited_attrs(Node *node,
*/
if (node && IsA(node, Query))
{
- Query *query = (Query *) node;
Query *newnode;
- FLATCOPY(newnode, query, Query);
- query_tree_mutator(newnode, adjust_inherited_attrs_mutator,
- (void *) &context, QTW_IGNORE_SUBQUERIES);
+ newnode = query_tree_mutator((Query *) node,
+ adjust_inherited_attrs_mutator,
+ (void *) &context,
+ QTW_IGNORE_RT_SUBQUERIES);
if (newnode->resultRelation == old_rt_index)
{
newnode->resultRelation = new_rt_index;
@@ -899,6 +894,7 @@ adjust_inherited_attrs_mutator(Node *node,
* already have been converted to subplans before we see them.
*/
Assert(!IsA(node, SubLink));
+ Assert(!IsA(node, Query));
/*
* BUT: although we don't need to recurse into subplans, we do need to
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 233a8cb8947..d9bdfec54e2 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.122 2003/01/15 19:35:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.123 2003/01/17 02:01:16 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -2153,7 +2153,7 @@ substitute_actual_parameters_mutator(Node *node,
* {
* adjust context for subquery;
* result = query_tree_walker((Query *) node, my_walker, context,
- * 0); // to visit rtable items too
+ * 0); // adjust flags as needed
* restore context if needed;
* return result;
* }
@@ -2414,7 +2414,7 @@ query_tree_walker(Query *query,
/* nothing to do */
break;
case RTE_SUBQUERY:
- if (! (flags & QTW_IGNORE_SUBQUERIES))
+ if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
if (walker(rte->subquery, context))
return true;
break;
@@ -2477,17 +2477,22 @@ query_tree_walker(Query *query,
* expression_tree_mutator include all those normally found in target lists
* and qualifier clauses during the planning stage.
*
+ * expression_tree_mutator will handle SubLink nodes by recursing normally
+ * into the "lefthand" arguments (which are expressions belonging to the outer
+ * plan). It will also call the mutator on the sub-Query node; however, when
+ * expression_tree_mutator itself is called on a Query node, it does nothing
+ * and returns the unmodified Query node. The net effect is that unless the
+ * mutator does something special at a Query node, sub-selects will not be
+ * visited or modified; the original sub-select will be linked to by the new
+ * SubLink node. Mutators that want to descend into sub-selects will usually
+ * do so by recognizing Query nodes and calling query_tree_mutator (below).
+ *
* expression_tree_mutator will handle a SubPlan node by recursing into
* the "exprs" and "args" lists (which belong to the outer plan), but it
* will simply copy the link to the inner plan, since that's typically what
* expression tree mutators want. A mutator that wants to modify the subplan
* can force appropriate behavior by recognizing SubPlan expression nodes
* and doing the right thing.
- *
- * SubLink nodes are handled by recursing into the "lefthand" argument list
- * only. (A SubLink will be seen only if the tree has not yet been
- * processed by subselect.c.) Again, this can be overridden by the mutator,
- * but it seems to be the most useful default behavior.
*--------------------
*/
@@ -2593,14 +2598,16 @@ expression_tree_mutator(Node *node,
break;
case T_SubLink:
{
- /*
- * We transform the lefthand side, but not the subquery.
- */
SubLink *sublink = (SubLink *) node;
SubLink *newnode;
FLATCOPY(newnode, sublink, SubLink);
MUTATE(newnode->lefthand, sublink->lefthand, List *);
+ /*
+ * Also invoke the mutator on the sublink's Query node, so
+ * it can recurse into the sub-query if it wants to.
+ */
+ MUTATE(newnode->subselect, sublink->subselect, Node *);
return (Node *) newnode;
}
break;
@@ -2707,6 +2714,9 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
+ case T_Query:
+ /* Do nothing with a sub-Query, per discussion above */
+ return node;
case T_List:
{
/*
@@ -2781,17 +2791,17 @@ expression_tree_mutator(Node *node,
* mutator intends to descend into subqueries. It is also useful for
* descending into subqueries within a mutator.
*
- * The specified Query node is modified-in-place; do a FLATCOPY() beforehand
- * if you don't want to change the original. All substructure is safely
- * copied, however.
- *
- * Some callers want to suppress mutating of certain items in the sub-Query,
+ * Some callers want to suppress mutating of certain items in the Query,
* typically because they need to process them specially, or don't actually
* want to recurse into subqueries. This is supported by the flags argument,
* which is the bitwise OR of flag values to suppress mutating of
* indicated items. (More flag bits may be added as needed.)
+ *
+ * Normally the Query node itself is copied, but some callers want it to be
+ * modified in-place; they must pass QTW_DONT_COPY_QUERY in flags. All
+ * modified substructure is safely copied in any case.
*/
-void
+Query *
query_tree_mutator(Query *query,
Node *(*mutator) (),
void *context,
@@ -2802,6 +2812,14 @@ query_tree_mutator(Query *query,
Assert(query != NULL && IsA(query, Query));
+ if (! (flags & QTW_DONT_COPY_QUERY))
+ {
+ Query *newquery;
+
+ FLATCOPY(newquery, query, Query);
+ query = newquery;
+ }
+
MUTATE(query->targetList, query->targetList, List *);
MUTATE(query->jointree, query->jointree, FromExpr *);
MUTATE(query->setOperations, query->setOperations, Node *);
@@ -2818,7 +2836,7 @@ query_tree_mutator(Query *query,
/* nothing to do, don't bother to make a copy */
break;
case RTE_SUBQUERY:
- if (! (flags & QTW_IGNORE_SUBQUERIES))
+ if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
{
FLATCOPY(newrte, rte, RangeTblEntry);
CHECKFLATCOPY(newrte->subquery, rte->subquery, Query);
@@ -2843,4 +2861,51 @@ query_tree_mutator(Query *query,
newrt = lappend(newrt, rte);
}
query->rtable = newrt;
+ return query;
+}
+
+/*
+ * query_or_expression_tree_walker --- hybrid form
+ *
+ * This routine will invoke query_tree_walker if called on a Query node,
+ * else will invoke the walker directly. This is a useful way of starting
+ * the recursion when the walker's normal change of state is not appropriate
+ * for the outermost Query node.
+ */
+bool
+query_or_expression_tree_walker(Node *node,
+ bool (*walker) (),
+ void *context,
+ int flags)
+{
+ if (node && IsA(node, Query))
+ return query_tree_walker((Query *) node,
+ walker,
+ context,
+ flags);
+ else
+ return walker(node, context);
+}
+
+/*
+ * query_or_expression_tree_mutator --- hybrid form
+ *
+ * This routine will invoke query_tree_mutator if called on a Query node,
+ * else will invoke the mutator directly. This is a useful way of starting
+ * the recursion when the mutator's normal change of state is not appropriate
+ * for the outermost Query node.
+ */
+Node *
+query_or_expression_tree_mutator(Node *node,
+ Node *(*mutator) (),
+ void *context,
+ int flags)
+{
+ if (node && IsA(node, Query))
+ return (Node *) query_tree_mutator((Query *) node,
+ mutator,
+ context,
+ flags);
+ else
+ return mutator(node, context);
}
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 47db90ad8a0..1eb9d9774ed 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.45 2003/01/16 18:26:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.46 2003/01/17 02:01:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,16 +20,6 @@
#include "parser/parsetree.h"
-/* macros borrowed from expression_tree_mutator */
-
-#define FLATCOPY(newnode, node, nodetype) \
- ( (newnode) = makeNode(nodetype), \
- memcpy((newnode), (node), sizeof(nodetype)) )
-
-#define MUTATE(newfield, oldfield, fieldtype, mutator, context) \
- ( (newfield) = (fieldtype) mutator((Node *) (oldfield), (context)) )
-
-
typedef struct
{
List *varlist;
@@ -87,14 +77,12 @@ pull_varnos(Node *node)
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- query_tree_walker((Query *) node, pull_varnos_walker,
- (void *) &context, 0);
- else
- pull_varnos_walker(node, &context);
+ query_or_expression_tree_walker(node,
+ pull_varnos_walker,
+ (void *) &context,
+ 0);
return context.varlist;
}
@@ -113,24 +101,6 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
context->varlist = lconsi(var->varno, context->varlist);
return false;
}
- if (is_subplan(node))
- {
- /*
- * Already-planned subquery. Examine the args list (parameters to
- * be passed to subquery), as well as the exprs list which is
- * executed by the outer query. But short-circuit recursion into
- * the subquery itself, which would be a waste of effort.
- */
- SubPlan *subplan = (SubPlan *) node;
-
- if (pull_varnos_walker((Node *) subplan->exprs,
- context))
- return true;
- if (pull_varnos_walker((Node *) subplan->args,
- context))
- return true;
- return false;
- }
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
@@ -169,15 +139,12 @@ contain_var_reference(Node *node, int varno, int varattno, int levelsup)
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- return query_tree_walker((Query *) node,
- contain_var_reference_walker,
- (void *) &context, 0);
- else
- return contain_var_reference_walker(node, &context);
+ return query_or_expression_tree_walker(node,
+ contain_var_reference_walker,
+ (void *) &context,
+ 0);
}
static bool
@@ -196,24 +163,6 @@ contain_var_reference_walker(Node *node,
return true;
return false;
}
- if (is_subplan(node))
- {
- /*
- * Already-planned subquery. Examine the args list (parameters to
- * be passed to subquery), as well as the exprs list which is
- * executed by the outer query. But short-circuit recursion into
- * the subquery itself, which would be a waste of effort.
- */
- SubPlan *subplan = (SubPlan *) node;
-
- if (contain_var_reference_walker((Node *) subplan->exprs,
- context))
- return true;
- if (contain_var_reference_walker((Node *) subplan->args,
- context))
- return true;
- return false;
- }
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
@@ -361,32 +310,16 @@ flatten_join_alias_vars_mutator(Node *node,
return flatten_join_alias_vars_mutator(newvar, context);
}
- /*
- * Since expression_tree_mutator won't touch subselects, we have to
- * handle them specially.
- */
- if (IsA(node, SubLink))
- {
- SubLink *sublink = (SubLink *) node;
- SubLink *newnode;
-
- FLATCOPY(newnode, sublink, SubLink);
- MUTATE(newnode->lefthand, sublink->lefthand, List *,
- flatten_join_alias_vars_mutator, context);
- MUTATE(newnode->subselect, sublink->subselect, Node *,
- flatten_join_alias_vars_mutator, context);
- return (Node *) newnode;
- }
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
- Query *query = (Query *) node;
Query *newnode;
- FLATCOPY(newnode, query, Query);
context->sublevels_up++;
- query_tree_mutator(newnode, flatten_join_alias_vars_mutator,
- (void *) context, QTW_IGNORE_JOINALIASES);
+ newnode = query_tree_mutator((Query *) node,
+ flatten_join_alias_vars_mutator,
+ (void *) context,
+ QTW_IGNORE_JOINALIASES);
context->sublevels_up--;
return (Node *) newnode;
}
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 3d13b9dd423..fb7412ca053 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.81 2002/12/05 04:04:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.82 2003/01/17 02:01:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -467,7 +467,7 @@ setRuleCheckAsUser(Query *qry, AclId userid)
/* ignore subqueries in rtable because we already processed them */
if (qry->hasSubLinks)
query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid,
- QTW_IGNORE_SUBQUERIES);
+ QTW_IGNORE_RT_SUBQUERIES);
}
/*
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index c19d15b4f02..5ddee1ab194 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.115 2002/12/17 01:18:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.116 2003/01/17 02:01:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -820,7 +820,7 @@ fireRIRrules(Query *parsetree)
*/
if (parsetree->hasSubLinks)
query_tree_walker(parsetree, fireRIRonSubLink, NULL,
- QTW_IGNORE_SUBQUERIES);
+ QTW_IGNORE_RT_SUBQUERIES);
/*
* If the query was marked having aggregates, check if this is still
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 22e7eee306c..4a4f6824b78 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.68 2002/12/12 15:49:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.69 2003/01/17 02:01:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,15 +22,6 @@
#include "utils/lsyscache.h"
-/* macros borrowed from expression_tree_mutator */
-
-#define FLATCOPY(newnode, node, nodetype) \
- ( (newnode) = makeNode(nodetype), \
- memcpy((newnode), (node), sizeof(nodetype)) )
-
-#define MUTATE(newfield, oldfield, fieldtype, mutator, context) \
- ( (newfield) = (fieldtype) mutator((Node *) (oldfield), (context)) )
-
static bool checkExprHasAggs_walker(Node *node, void *context);
static bool checkExprHasSubLink_walker(Node *node, void *context);
@@ -47,11 +38,10 @@ checkExprHasAggs(Node *node)
* If a Query is passed, examine it --- but we will not recurse into
* sub-Queries.
*/
- if (node && IsA(node, Query))
- return query_tree_walker((Query *) node, checkExprHasAggs_walker,
- NULL, QTW_IGNORE_SUBQUERIES);
- else
- return checkExprHasAggs_walker(node, NULL);
+ return query_or_expression_tree_walker(node,
+ checkExprHasAggs_walker,
+ NULL,
+ QTW_IGNORE_RT_SUBQUERIES);
}
static bool
@@ -77,11 +67,10 @@ checkExprHasSubLink(Node *node)
* If a Query is passed, examine it --- but we will not recurse into
* sub-Queries.
*/
- if (node && IsA(node, Query))
- return query_tree_walker((Query *) node, checkExprHasSubLink_walker,
- NULL, QTW_IGNORE_SUBQUERIES);
- else
- return checkExprHasSubLink_walker(node, NULL);
+ return query_or_expression_tree_walker(node,
+ checkExprHasSubLink_walker,
+ NULL,
+ QTW_IGNORE_RT_SUBQUERIES);
}
static bool
@@ -380,14 +369,12 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker,
- (void *) &context, 0);
- else
- IncrementVarSublevelsUp_walker(node, &context);
+ query_or_expression_tree_walker(node,
+ IncrementVarSublevelsUp_walker,
+ (void *) &context,
+ 0);
}
@@ -461,14 +448,12 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- return query_tree_walker((Query *) node, rangeTableEntry_used_walker,
- (void *) &context, 0);
- else
- return rangeTableEntry_used_walker(node, &context);
+ return query_or_expression_tree_walker(node,
+ rangeTableEntry_used_walker,
+ (void *) &context,
+ 0);
}
@@ -527,14 +512,12 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_walker to make sure that
- * sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- return query_tree_walker((Query *) node, attribute_used_walker,
- (void *) &context, 0);
- else
- return attribute_used_walker(node, &context);
+ return query_or_expression_tree_walker(node,
+ attribute_used_walker,
+ (void *) &context,
+ 0);
}
@@ -820,30 +803,16 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
/* otherwise fall through to copy the var normally */
}
- /*
- * Since expression_tree_mutator won't touch subselects, we have to
- * handle them specially.
- */
- if (IsA(node, SubLink))
- {
- SubLink *sublink = (SubLink *) node;
- SubLink *newnode;
-
- FLATCOPY(newnode, sublink, SubLink);
- MUTATE(newnode->lefthand, sublink->lefthand, List *,
- ResolveNew_mutator, context);
- MUTATE(newnode->subselect, sublink->subselect, Node *,
- ResolveNew_mutator, context);
- return (Node *) newnode;
- }
if (IsA(node, Query))
{
- Query *query = (Query *) node;
+ /* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *newnode;
- FLATCOPY(newnode, query, Query);
context->sublevels_up++;
- query_tree_mutator(newnode, ResolveNew_mutator, context, 0);
+ newnode = query_tree_mutator((Query *) node,
+ ResolveNew_mutator,
+ (void *) context,
+ 0);
context->sublevels_up--;
return (Node *) newnode;
}
@@ -865,21 +834,12 @@ ResolveNew(Node *node, int target_varno, int sublevels_up,
/*
* Must be prepared to start with a Query or a bare expression tree;
- * if it's a Query, go straight to query_tree_mutator to make sure
- * that sublevels_up doesn't get incremented prematurely.
+ * if it's a Query, we don't want to increment sublevels_up.
*/
- if (node && IsA(node, Query))
- {
- Query *query = (Query *) node;
- Query *newnode;
-
- FLATCOPY(newnode, query, Query);
- query_tree_mutator(newnode, ResolveNew_mutator,
- (void *) &context, 0);
- return (Node *) newnode;
- }
- else
- return ResolveNew_mutator(node, &context);
+ return query_or_expression_tree_mutator(node,
+ ResolveNew_mutator,
+ (void *) &context,
+ 0);
}
@@ -959,31 +919,16 @@ HandleRIRAttributeRule_mutator(Node *node,
/* otherwise fall through to copy the var normally */
}
- /*
- * Since expression_tree_mutator won't touch subselects, we have to
- * handle them specially.
- */
- if (IsA(node, SubLink))
- {
- SubLink *sublink = (SubLink *) node;
- SubLink *newnode;
-
- FLATCOPY(newnode, sublink, SubLink);
- MUTATE(newnode->lefthand, sublink->lefthand, List *,
- HandleRIRAttributeRule_mutator, context);
- MUTATE(newnode->subselect, sublink->subselect, Node *,
- HandleRIRAttributeRule_mutator, context);
- return (Node *) newnode;
- }
if (IsA(node, Query))
{
- Query *query = (Query *) node;
+ /* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *newnode;
- FLATCOPY(newnode, query, Query);
context->sublevels_up++;
- query_tree_mutator(newnode, HandleRIRAttributeRule_mutator,
- context, 0);
+ newnode = query_tree_mutator((Query *) node,
+ HandleRIRAttributeRule_mutator,
+ (void *) context,
+ 0);
context->sublevels_up--;
return (Node *) newnode;
}
@@ -1010,8 +955,10 @@ HandleRIRAttributeRule(Query *parsetree,
context.badsql = badsql;
context.sublevels_up = 0;
- query_tree_mutator(parsetree, HandleRIRAttributeRule_mutator,
- (void *) &context, 0);
+ query_tree_mutator(parsetree,
+ HandleRIRAttributeRule_mutator,
+ (void *) &context,
+ QTW_DONT_COPY_QUERY);
}
#endif /* NOT_USED */
diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h
index 4ed022b15e7..024c1599a4c 100644
--- a/src/include/optimizer/clauses.h
+++ b/src/include/optimizer/clauses.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: clauses.h,v 1.59 2003/01/15 19:35:47 tgl Exp $
+ * $Id: clauses.h,v 1.60 2003/01/17 02:01:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -75,12 +75,18 @@ extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
void *context);
/* flags bits for query_tree_walker and query_tree_mutator */
-#define QTW_IGNORE_SUBQUERIES 0x01 /* subqueries in rtable */
-#define QTW_IGNORE_JOINALIASES 0x02 /* JOIN alias var lists */
+#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
+#define QTW_IGNORE_JOINALIASES 0x02 /* JOIN alias var lists */
+#define QTW_DONT_COPY_QUERY 0x04 /* do not copy top Query */
extern bool query_tree_walker(Query *query, bool (*walker) (),
void *context, int flags);
-extern void query_tree_mutator(Query *query, Node *(*mutator) (),
- void *context, int flags);
+extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
+ void *context, int flags);
+
+extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
+ void *context, int flags);
+extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
+ void *context, int flags);
#endif /* CLAUSES_H */