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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy