Skip to content

Commit a4d82dd

Browse files
committed
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.
1 parent 227a404 commit a4d82dd

File tree

8 files changed

+167
-220
lines changed

8 files changed

+167
-220
lines changed

src/backend/optimizer/plan/subselect.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.66 2003/01/13 18:10:53 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.67 2003/01/17 02:01:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -628,12 +628,12 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
628628
}
629629

630630
/*
631-
* Note that we will never see a SubPlan expression in the input
632-
* (since this is the very routine that creates 'em to begin with). So
633-
* the code in expression_tree_mutator() that might do inappropriate
634-
* things with SubPlans or SubLinks will not be exercised.
631+
* We should never see a SubPlan expression in the input (since this is
632+
* the very routine that creates 'em to begin with). We shouldn't find
633+
* ourselves invoked directly on a Query, either.
635634
*/
636635
Assert(!is_subplan(node));
636+
Assert(!IsA(node, Query));
637637

638638
/*
639639
* If we recurse down through anything other than a List node, we are

src/backend/optimizer/prep/prepunion.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.86 2003/01/15 19:35:44 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.87 2003/01/17 02:01:16 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -34,11 +34,6 @@
3434
#include "parser/parsetree.h"
3535
#include "utils/lsyscache.h"
3636

37-
/* macros borrowed from expression_tree_mutator */
38-
39-
#define FLATCOPY(newnode, node, nodetype) \
40-
( (newnode) = makeNode(nodetype), \
41-
memcpy((newnode), (node), sizeof(nodetype)) )
4237

4338
typedef struct
4439
{
@@ -765,12 +760,12 @@ adjust_inherited_attrs(Node *node,
765760
*/
766761
if (node && IsA(node, Query))
767762
{
768-
Query *query = (Query *) node;
769763
Query *newnode;
770764

771-
FLATCOPY(newnode, query, Query);
772-
query_tree_mutator(newnode, adjust_inherited_attrs_mutator,
773-
(void *) &context, QTW_IGNORE_SUBQUERIES);
765+
newnode = query_tree_mutator((Query *) node,
766+
adjust_inherited_attrs_mutator,
767+
(void *) &context,
768+
QTW_IGNORE_RT_SUBQUERIES);
774769
if (newnode->resultRelation == old_rt_index)
775770
{
776771
newnode->resultRelation = new_rt_index;
@@ -899,6 +894,7 @@ adjust_inherited_attrs_mutator(Node *node,
899894
* already have been converted to subplans before we see them.
900895
*/
901896
Assert(!IsA(node, SubLink));
897+
Assert(!IsA(node, Query));
902898

903899
/*
904900
* BUT: although we don't need to recurse into subplans, we do need to

src/backend/optimizer/util/clauses.c

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.122 2003/01/15 19:35:44 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.123 2003/01/17 02:01:16 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHOR DATE MAJOR EVENT
@@ -2153,7 +2153,7 @@ substitute_actual_parameters_mutator(Node *node,
21532153
* {
21542154
* adjust context for subquery;
21552155
* result = query_tree_walker((Query *) node, my_walker, context,
2156-
* 0); // to visit rtable items too
2156+
* 0); // adjust flags as needed
21572157
* restore context if needed;
21582158
* return result;
21592159
* }
@@ -2414,7 +2414,7 @@ query_tree_walker(Query *query,
24142414
/* nothing to do */
24152415
break;
24162416
case RTE_SUBQUERY:
2417-
if (! (flags & QTW_IGNORE_SUBQUERIES))
2417+
if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
24182418
if (walker(rte->subquery, context))
24192419
return true;
24202420
break;
@@ -2477,17 +2477,22 @@ query_tree_walker(Query *query,
24772477
* expression_tree_mutator include all those normally found in target lists
24782478
* and qualifier clauses during the planning stage.
24792479
*
2480+
* expression_tree_mutator will handle SubLink nodes by recursing normally
2481+
* into the "lefthand" arguments (which are expressions belonging to the outer
2482+
* plan). It will also call the mutator on the sub-Query node; however, when
2483+
* expression_tree_mutator itself is called on a Query node, it does nothing
2484+
* and returns the unmodified Query node. The net effect is that unless the
2485+
* mutator does something special at a Query node, sub-selects will not be
2486+
* visited or modified; the original sub-select will be linked to by the new
2487+
* SubLink node. Mutators that want to descend into sub-selects will usually
2488+
* do so by recognizing Query nodes and calling query_tree_mutator (below).
2489+
*
24802490
* expression_tree_mutator will handle a SubPlan node by recursing into
24812491
* the "exprs" and "args" lists (which belong to the outer plan), but it
24822492
* will simply copy the link to the inner plan, since that's typically what
24832493
* expression tree mutators want. A mutator that wants to modify the subplan
24842494
* can force appropriate behavior by recognizing SubPlan expression nodes
24852495
* and doing the right thing.
2486-
*
2487-
* SubLink nodes are handled by recursing into the "lefthand" argument list
2488-
* only. (A SubLink will be seen only if the tree has not yet been
2489-
* processed by subselect.c.) Again, this can be overridden by the mutator,
2490-
* but it seems to be the most useful default behavior.
24912496
*--------------------
24922497
*/
24932498

@@ -2593,14 +2598,16 @@ expression_tree_mutator(Node *node,
25932598
break;
25942599
case T_SubLink:
25952600
{
2596-
/*
2597-
* We transform the lefthand side, but not the subquery.
2598-
*/
25992601
SubLink *sublink = (SubLink *) node;
26002602
SubLink *newnode;
26012603

26022604
FLATCOPY(newnode, sublink, SubLink);
26032605
MUTATE(newnode->lefthand, sublink->lefthand, List *);
2606+
/*
2607+
* Also invoke the mutator on the sublink's Query node, so
2608+
* it can recurse into the sub-query if it wants to.
2609+
*/
2610+
MUTATE(newnode->subselect, sublink->subselect, Node *);
26042611
return (Node *) newnode;
26052612
}
26062613
break;
@@ -2707,6 +2714,9 @@ expression_tree_mutator(Node *node,
27072714
return (Node *) newnode;
27082715
}
27092716
break;
2717+
case T_Query:
2718+
/* Do nothing with a sub-Query, per discussion above */
2719+
return node;
27102720
case T_List:
27112721
{
27122722
/*
@@ -2781,17 +2791,17 @@ expression_tree_mutator(Node *node,
27812791
* mutator intends to descend into subqueries. It is also useful for
27822792
* descending into subqueries within a mutator.
27832793
*
2784-
* The specified Query node is modified-in-place; do a FLATCOPY() beforehand
2785-
* if you don't want to change the original. All substructure is safely
2786-
* copied, however.
2787-
*
2788-
* Some callers want to suppress mutating of certain items in the sub-Query,
2794+
* Some callers want to suppress mutating of certain items in the Query,
27892795
* typically because they need to process them specially, or don't actually
27902796
* want to recurse into subqueries. This is supported by the flags argument,
27912797
* which is the bitwise OR of flag values to suppress mutating of
27922798
* indicated items. (More flag bits may be added as needed.)
2799+
*
2800+
* Normally the Query node itself is copied, but some callers want it to be
2801+
* modified in-place; they must pass QTW_DONT_COPY_QUERY in flags. All
2802+
* modified substructure is safely copied in any case.
27932803
*/
2794-
void
2804+
Query *
27952805
query_tree_mutator(Query *query,
27962806
Node *(*mutator) (),
27972807
void *context,
@@ -2802,6 +2812,14 @@ query_tree_mutator(Query *query,
28022812

28032813
Assert(query != NULL && IsA(query, Query));
28042814

2815+
if (! (flags & QTW_DONT_COPY_QUERY))
2816+
{
2817+
Query *newquery;
2818+
2819+
FLATCOPY(newquery, query, Query);
2820+
query = newquery;
2821+
}
2822+
28052823
MUTATE(query->targetList, query->targetList, List *);
28062824
MUTATE(query->jointree, query->jointree, FromExpr *);
28072825
MUTATE(query->setOperations, query->setOperations, Node *);
@@ -2818,7 +2836,7 @@ query_tree_mutator(Query *query,
28182836
/* nothing to do, don't bother to make a copy */
28192837
break;
28202838
case RTE_SUBQUERY:
2821-
if (! (flags & QTW_IGNORE_SUBQUERIES))
2839+
if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
28222840
{
28232841
FLATCOPY(newrte, rte, RangeTblEntry);
28242842
CHECKFLATCOPY(newrte->subquery, rte->subquery, Query);
@@ -2843,4 +2861,51 @@ query_tree_mutator(Query *query,
28432861
newrt = lappend(newrt, rte);
28442862
}
28452863
query->rtable = newrt;
2864+
return query;
2865+
}
2866+
2867+
/*
2868+
* query_or_expression_tree_walker --- hybrid form
2869+
*
2870+
* This routine will invoke query_tree_walker if called on a Query node,
2871+
* else will invoke the walker directly. This is a useful way of starting
2872+
* the recursion when the walker's normal change of state is not appropriate
2873+
* for the outermost Query node.
2874+
*/
2875+
bool
2876+
query_or_expression_tree_walker(Node *node,
2877+
bool (*walker) (),
2878+
void *context,
2879+
int flags)
2880+
{
2881+
if (node && IsA(node, Query))
2882+
return query_tree_walker((Query *) node,
2883+
walker,
2884+
context,
2885+
flags);
2886+
else
2887+
return walker(node, context);
2888+
}
2889+
2890+
/*
2891+
* query_or_expression_tree_mutator --- hybrid form
2892+
*
2893+
* This routine will invoke query_tree_mutator if called on a Query node,
2894+
* else will invoke the mutator directly. This is a useful way of starting
2895+
* the recursion when the mutator's normal change of state is not appropriate
2896+
* for the outermost Query node.
2897+
*/
2898+
Node *
2899+
query_or_expression_tree_mutator(Node *node,
2900+
Node *(*mutator) (),
2901+
void *context,
2902+
int flags)
2903+
{
2904+
if (node && IsA(node, Query))
2905+
return (Node *) query_tree_mutator((Query *) node,
2906+
mutator,
2907+
context,
2908+
flags);
2909+
else
2910+
return mutator(node, context);
28462911
}

0 commit comments

Comments
 (0)