]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Adjust API of expression_tree_mutator and query_tree_mutator to
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Jan 2003 02:01:21 +0000 (02:01 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Jan 2003 02:01:21 +0000 (02:01 +0000)
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.

src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/var.c
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/include/optimizer/clauses.h

index 3c72199777eefb7c507b3f9800bad5c6f448ad65..b30454dcae268d741d1405e1f23f8982e6342f2e 100644 (file)
@@ -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
index 4af395b860c2b43d0cbca0946d6f6f71f0e2d1d8..807364fac8d8c83a197f21bc86ef023238204751 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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
index 233a8cb8947d45dd0384c756703f89d75942f72d..d9bdfec54e2cb69852c5bdd1a911a1a4263a9ac4 100644 (file)
@@ -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);
 }
index 47db90ad8a05e41913522adb61b3ab4c74e69aaf..1eb9d9774ed7434694b8c7aebb2592ca90e5fc34 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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;
        }
index 3d13b9dd423cd388e51119ac19ad1221c4da9b28..fb7412ca053f911cf4503b7fc6fcca0df8f7450b 100644 (file)
@@ -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);
 }
 
 /*
index c19d15b4f027ca98137a39c8d5d5c2670fced0f0..5ddee1ab194da0485ef5903db4ff415095843170 100644 (file)
@@ -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
index 22e7eee306c50f395602c6fb4de187345307596b..4a4f6824b789691b448f35fd8104a0f99bbb4adf 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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 */
index 4ed022b15e766c4de1006cd32b7f43b639bbb47a..024c1599a4c77d08dd158138e851a5e4eec10f1c 100644 (file)
@@ -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 */