8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.212 2007/01/20 20:45:39 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.213 2007/02/19 07:03:29 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
42
42
#include "utils/syscache.h"
43
43
44
44
45
- ParamListInfo PlannerBoundParamList = NULL ; /* current boundParams */
46
-
47
-
48
45
/* Expression kind codes for preprocess_expression */
49
46
#define EXPRKIND_QUAL 0
50
47
#define EXPRKIND_TARGET 1
@@ -86,35 +83,21 @@ Plan *
86
83
planner (Query * parse , bool isCursor , int cursorOptions ,
87
84
ParamListInfo boundParams )
88
85
{
86
+ PlannerGlobal * glob ;
89
87
double tuple_fraction ;
90
88
Plan * result_plan ;
91
- Index save_PlannerQueryLevel ;
92
- List * save_PlannerParamList ;
93
- ParamListInfo save_PlannerBoundParamList ;
94
89
95
90
/*
96
- * The planner can be called recursively (an example is when
97
- * eval_const_expressions tries to pre-evaluate an SQL function). So,
98
- * these global state variables must be saved and restored.
99
- *
100
- * Query level and the param list cannot be moved into the per-query
101
- * PlannerInfo structure since their whole purpose is communication across
102
- * multiple sub-queries. Also, boundParams is explicitly info from outside
103
- * the query, and so is likewise better handled as a global variable.
104
- *
105
- * Note we do NOT save and restore PlannerPlanId: it exists to assign
106
- * unique IDs to SubPlan nodes, and we want those IDs to be unique for the
107
- * life of a backend. Also, PlannerInitPlan is saved/restored in
108
- * subquery_planner, not here.
91
+ * Set up global state for this planner invocation. This data is needed
92
+ * across all levels of sub-Query that might exist in the given command,
93
+ * so we keep it in a separate struct that's linked to by each per-Query
94
+ * PlannerInfo.
109
95
*/
110
- save_PlannerQueryLevel = PlannerQueryLevel ;
111
- save_PlannerParamList = PlannerParamList ;
112
- save_PlannerBoundParamList = PlannerBoundParamList ;
96
+ glob = makeNode (PlannerGlobal );
113
97
114
- /* Initialize state for handling outer-level references and params */
115
- PlannerQueryLevel = 0 ; /* will be 1 in top-level subquery_planner */
116
- PlannerParamList = NIL ;
117
- PlannerBoundParamList = boundParams ;
98
+ glob -> boundParams = boundParams ;
99
+ glob -> paramlist = NIL ;
100
+ glob -> next_plan_id = 0 ;
118
101
119
102
/* Determine what fraction of the plan is likely to be scanned */
120
103
if (isCursor )
@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
134
117
}
135
118
136
119
/* primary planning entry point (may recurse for subqueries) */
137
- result_plan = subquery_planner (parse , tuple_fraction , NULL );
138
-
139
- /* check we popped out the right number of levels */
140
- Assert (PlannerQueryLevel == 0 );
120
+ result_plan = subquery_planner (glob , parse , 1 , tuple_fraction , NULL );
141
121
142
122
/*
143
123
* If creating a plan for a scrollable cursor, make sure it can run
@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
153
133
result_plan = set_plan_references (result_plan , parse -> rtable );
154
134
155
135
/* executor wants to know total number of Params used overall */
156
- result_plan -> nParamExec = list_length (PlannerParamList );
157
-
158
- /* restore state for outer planner, if any */
159
- PlannerQueryLevel = save_PlannerQueryLevel ;
160
- PlannerParamList = save_PlannerParamList ;
161
- PlannerBoundParamList = save_PlannerBoundParamList ;
136
+ result_plan -> nParamExec = list_length (glob -> paramlist );
162
137
163
138
return result_plan ;
164
139
}
@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
169
144
* Invokes the planner on a subquery. We recurse to here for each
170
145
* sub-SELECT found in the query tree.
171
146
*
147
+ * glob is the global state for the current planner run.
172
148
* parse is the querytree produced by the parser & rewriter.
149
+ * level is the current recursion depth (1 at the top-level Query).
173
150
* tuple_fraction is the fraction of tuples we expect will be retrieved.
174
151
* tuple_fraction is interpreted as explained for grouping_planner, below.
175
152
*
@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions,
189
166
*--------------------
190
167
*/
191
168
Plan *
192
- subquery_planner (Query * parse , double tuple_fraction ,
169
+ subquery_planner (PlannerGlobal * glob , Query * parse ,
170
+ Index level , double tuple_fraction ,
193
171
List * * subquery_pathkeys )
194
172
{
195
- List * saved_initplan = PlannerInitPlan ;
196
- int saved_planid = PlannerPlanId ;
173
+ int saved_plan_id = glob -> next_plan_id ;
197
174
PlannerInfo * root ;
198
175
Plan * plan ;
199
176
List * newHaving ;
200
177
ListCell * l ;
201
178
202
- /* Set up for a new level of subquery */
203
- PlannerQueryLevel ++ ;
204
- PlannerInitPlan = NIL ;
205
-
206
179
/* Create a PlannerInfo data structure for this subquery */
207
180
root = makeNode (PlannerInfo );
208
181
root -> parse = parse ;
182
+ root -> glob = glob ;
183
+ root -> query_level = level ;
209
184
root -> planner_cxt = CurrentMemoryContext ;
185
+ root -> init_plans = NIL ;
210
186
root -> eq_classes = NIL ;
211
187
root -> in_info_list = NIL ;
212
188
root -> append_rel_list = NIL ;
@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction,
396
372
* initPlan list and extParam/allParam sets for plan nodes, and attach the
397
373
* initPlans to the top plan node.
398
374
*/
399
- if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1 )
400
- SS_finalize_plan (plan , parse -> rtable );
375
+ if (root -> glob -> next_plan_id != saved_plan_id || root -> query_level > 1 )
376
+ SS_finalize_plan (root , plan );
401
377
402
378
/* Return sort ordering info if caller wants it */
403
379
if (subquery_pathkeys )
404
380
* subquery_pathkeys = root -> query_pathkeys ;
405
381
406
- /* Return to outer subquery context */
407
- PlannerQueryLevel -- ;
408
- PlannerInitPlan = saved_initplan ;
409
- /* we do NOT restore PlannerPlanId; that's not an oversight! */
410
-
411
382
return plan ;
412
383
}
413
384
@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
460
431
if (kind != EXPRKIND_VALUES &&
461
432
(root -> parse -> jointree -> fromlist != NIL ||
462
433
kind == EXPRKIND_QUAL ||
463
- PlannerQueryLevel > 1 ))
434
+ root -> query_level > 1 ))
464
435
expr = eval_const_expressions (expr );
465
436
466
437
/*
@@ -478,16 +449,16 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
478
449
479
450
/* Expand SubLinks to SubPlans */
480
451
if (root -> parse -> hasSubLinks )
481
- expr = SS_process_sublinks (expr , (kind == EXPRKIND_QUAL ));
452
+ expr = SS_process_sublinks (root , expr , (kind == EXPRKIND_QUAL ));
482
453
483
454
/*
484
455
* XXX do not insert anything here unless you have grokked the comments in
485
456
* SS_replace_correlation_vars ...
486
457
*/
487
458
488
459
/* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
489
- if (PlannerQueryLevel > 1 )
490
- expr = SS_replace_correlation_vars (expr );
460
+ if (root -> query_level > 1 )
461
+ expr = SS_replace_correlation_vars (root , expr );
491
462
492
463
/*
493
464
* If it's a qual or havingQual, convert it to implicit-AND format. (We
@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root)
590
561
subroot .in_info_list = (List * )
591
562
adjust_appendrel_attrs ((Node * ) root -> in_info_list ,
592
563
appinfo );
564
+ subroot .init_plans = NIL ;
593
565
/* There shouldn't be any OJ info to translate, as yet */
594
566
Assert (subroot .oj_info_list == NIL );
595
567
@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root)
612
584
613
585
subplans = lappend (subplans , subplan );
614
586
587
+ /* Make sure any initplans from this rel get into the outer list */
588
+ root -> init_plans = list_concat (root -> init_plans , subroot .init_plans );
589
+
615
590
/* Build target-relations list for the executor */
616
591
resultRelations = lappend_int (resultRelations , appinfo -> child_relid );
617
592
@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
1201
1176
*/
1202
1177
if (parse -> limitCount )
1203
1178
{
1204
- est = estimate_expression_value (parse -> limitCount );
1179
+ est = estimate_expression_value (root , parse -> limitCount );
1205
1180
if (est && IsA (est , Const ))
1206
1181
{
1207
1182
if (((Const * ) est )-> constisnull )
@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
1224
1199
1225
1200
if (parse -> limitOffset )
1226
1201
{
1227
- est = estimate_expression_value (parse -> limitOffset );
1202
+ est = estimate_expression_value (root , parse -> limitOffset );
1228
1203
if (est && IsA (est , Const ))
1229
1204
{
1230
1205
if (((Const * ) est )-> constisnull )
0 commit comments