8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
* HISTORY
14
14
* AUTHOR DATE MAJOR EVENT
@@ -2153,7 +2153,7 @@ substitute_actual_parameters_mutator(Node *node,
2153
2153
* {
2154
2154
* adjust context for subquery;
2155
2155
* result = query_tree_walker((Query *) node, my_walker, context,
2156
- * 0); // to visit rtable items too
2156
+ * 0); // adjust flags as needed
2157
2157
* restore context if needed;
2158
2158
* return result;
2159
2159
* }
@@ -2414,7 +2414,7 @@ query_tree_walker(Query *query,
2414
2414
/* nothing to do */
2415
2415
break ;
2416
2416
case RTE_SUBQUERY :
2417
- if (! (flags & QTW_IGNORE_SUBQUERIES ))
2417
+ if (! (flags & QTW_IGNORE_RT_SUBQUERIES ))
2418
2418
if (walker (rte -> subquery , context ))
2419
2419
return true;
2420
2420
break ;
@@ -2477,17 +2477,22 @@ query_tree_walker(Query *query,
2477
2477
* expression_tree_mutator include all those normally found in target lists
2478
2478
* and qualifier clauses during the planning stage.
2479
2479
*
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
+ *
2480
2490
* expression_tree_mutator will handle a SubPlan node by recursing into
2481
2491
* the "exprs" and "args" lists (which belong to the outer plan), but it
2482
2492
* will simply copy the link to the inner plan, since that's typically what
2483
2493
* expression tree mutators want. A mutator that wants to modify the subplan
2484
2494
* can force appropriate behavior by recognizing SubPlan expression nodes
2485
2495
* 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.
2491
2496
*--------------------
2492
2497
*/
2493
2498
@@ -2593,14 +2598,16 @@ expression_tree_mutator(Node *node,
2593
2598
break ;
2594
2599
case T_SubLink :
2595
2600
{
2596
- /*
2597
- * We transform the lefthand side, but not the subquery.
2598
- */
2599
2601
SubLink * sublink = (SubLink * ) node ;
2600
2602
SubLink * newnode ;
2601
2603
2602
2604
FLATCOPY (newnode , sublink , SubLink );
2603
2605
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 * );
2604
2611
return (Node * ) newnode ;
2605
2612
}
2606
2613
break ;
@@ -2707,6 +2714,9 @@ expression_tree_mutator(Node *node,
2707
2714
return (Node * ) newnode ;
2708
2715
}
2709
2716
break ;
2717
+ case T_Query :
2718
+ /* Do nothing with a sub-Query, per discussion above */
2719
+ return node ;
2710
2720
case T_List :
2711
2721
{
2712
2722
/*
@@ -2781,17 +2791,17 @@ expression_tree_mutator(Node *node,
2781
2791
* mutator intends to descend into subqueries. It is also useful for
2782
2792
* descending into subqueries within a mutator.
2783
2793
*
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,
2789
2795
* typically because they need to process them specially, or don't actually
2790
2796
* want to recurse into subqueries. This is supported by the flags argument,
2791
2797
* which is the bitwise OR of flag values to suppress mutating of
2792
2798
* 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.
2793
2803
*/
2794
- void
2804
+ Query *
2795
2805
query_tree_mutator (Query * query ,
2796
2806
Node * (* mutator ) (),
2797
2807
void * context ,
@@ -2802,6 +2812,14 @@ query_tree_mutator(Query *query,
2802
2812
2803
2813
Assert (query != NULL && IsA (query , Query ));
2804
2814
2815
+ if (! (flags & QTW_DONT_COPY_QUERY ))
2816
+ {
2817
+ Query * newquery ;
2818
+
2819
+ FLATCOPY (newquery , query , Query );
2820
+ query = newquery ;
2821
+ }
2822
+
2805
2823
MUTATE (query -> targetList , query -> targetList , List * );
2806
2824
MUTATE (query -> jointree , query -> jointree , FromExpr * );
2807
2825
MUTATE (query -> setOperations , query -> setOperations , Node * );
@@ -2818,7 +2836,7 @@ query_tree_mutator(Query *query,
2818
2836
/* nothing to do, don't bother to make a copy */
2819
2837
break ;
2820
2838
case RTE_SUBQUERY :
2821
- if (! (flags & QTW_IGNORE_SUBQUERIES ))
2839
+ if (! (flags & QTW_IGNORE_RT_SUBQUERIES ))
2822
2840
{
2823
2841
FLATCOPY (newrte , rte , RangeTblEntry );
2824
2842
CHECKFLATCOPY (newrte -> subquery , rte -> subquery , Query );
@@ -2843,4 +2861,51 @@ query_tree_mutator(Query *query,
2843
2861
newrt = lappend (newrt , rte );
2844
2862
}
2845
2863
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 );
2846
2911
}
0 commit comments