88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
4242#include "utils/syscache.h"
4343
4444
45- ParamListInfo PlannerBoundParamList = NULL ; /* current boundParams */
46-
47-
4845/* Expression kind codes for preprocess_expression */
4946#define EXPRKIND_QUAL 0
5047#define EXPRKIND_TARGET 1
@@ -86,35 +83,21 @@ Plan *
8683planner (Query * parse , bool isCursor , int cursorOptions ,
8784 ParamListInfo boundParams )
8885{
86+ PlannerGlobal * glob ;
8987 double tuple_fraction ;
9088 Plan * result_plan ;
91- Index save_PlannerQueryLevel ;
92- List * save_PlannerParamList ;
93- ParamListInfo save_PlannerBoundParamList ;
9489
9590 /*
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.
10995 */
110- save_PlannerQueryLevel = PlannerQueryLevel ;
111- save_PlannerParamList = PlannerParamList ;
112- save_PlannerBoundParamList = PlannerBoundParamList ;
96+ glob = makeNode (PlannerGlobal );
11397
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 ;
118101
119102 /* Determine what fraction of the plan is likely to be scanned */
120103 if (isCursor )
@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
134117 }
135118
136119 /* 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 );
141121
142122 /*
143123 * If creating a plan for a scrollable cursor, make sure it can run
@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
153133 result_plan = set_plan_references (result_plan , parse -> rtable );
154134
155135 /* 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 );
162137
163138 return result_plan ;
164139}
@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
169144 * Invokes the planner on a subquery. We recurse to here for each
170145 * sub-SELECT found in the query tree.
171146 *
147+ * glob is the global state for the current planner run.
172148 * parse is the querytree produced by the parser & rewriter.
149+ * level is the current recursion depth (1 at the top-level Query).
173150 * tuple_fraction is the fraction of tuples we expect will be retrieved.
174151 * tuple_fraction is interpreted as explained for grouping_planner, below.
175152 *
@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions,
189166 *--------------------
190167 */
191168Plan *
192- subquery_planner (Query * parse , double tuple_fraction ,
169+ subquery_planner (PlannerGlobal * glob , Query * parse ,
170+ Index level , double tuple_fraction ,
193171 List * * subquery_pathkeys )
194172{
195- List * saved_initplan = PlannerInitPlan ;
196- int saved_planid = PlannerPlanId ;
173+ int saved_plan_id = glob -> next_plan_id ;
197174 PlannerInfo * root ;
198175 Plan * plan ;
199176 List * newHaving ;
200177 ListCell * l ;
201178
202- /* Set up for a new level of subquery */
203- PlannerQueryLevel ++ ;
204- PlannerInitPlan = NIL ;
205-
206179 /* Create a PlannerInfo data structure for this subquery */
207180 root = makeNode (PlannerInfo );
208181 root -> parse = parse ;
182+ root -> glob = glob ;
183+ root -> query_level = level ;
209184 root -> planner_cxt = CurrentMemoryContext ;
185+ root -> init_plans = NIL ;
210186 root -> eq_classes = NIL ;
211187 root -> in_info_list = NIL ;
212188 root -> append_rel_list = NIL ;
@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction,
396372 * initPlan list and extParam/allParam sets for plan nodes, and attach the
397373 * initPlans to the top plan node.
398374 */
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 );
401377
402378 /* Return sort ordering info if caller wants it */
403379 if (subquery_pathkeys )
404380 * subquery_pathkeys = root -> query_pathkeys ;
405381
406- /* Return to outer subquery context */
407- PlannerQueryLevel -- ;
408- PlannerInitPlan = saved_initplan ;
409- /* we do NOT restore PlannerPlanId; that's not an oversight! */
410-
411382 return plan ;
412383}
413384
@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
460431 if (kind != EXPRKIND_VALUES &&
461432 (root -> parse -> jointree -> fromlist != NIL ||
462433 kind == EXPRKIND_QUAL ||
463- PlannerQueryLevel > 1 ))
434+ root -> query_level > 1 ))
464435 expr = eval_const_expressions (expr );
465436
466437 /*
@@ -478,16 +449,16 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
478449
479450 /* Expand SubLinks to SubPlans */
480451 if (root -> parse -> hasSubLinks )
481- expr = SS_process_sublinks (expr , (kind == EXPRKIND_QUAL ));
452+ expr = SS_process_sublinks (root , expr , (kind == EXPRKIND_QUAL ));
482453
483454 /*
484455 * XXX do not insert anything here unless you have grokked the comments in
485456 * SS_replace_correlation_vars ...
486457 */
487458
488459 /* 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 );
491462
492463 /*
493464 * If it's a qual or havingQual, convert it to implicit-AND format. (We
@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root)
590561 subroot .in_info_list = (List * )
591562 adjust_appendrel_attrs ((Node * ) root -> in_info_list ,
592563 appinfo );
564+ subroot .init_plans = NIL ;
593565 /* There shouldn't be any OJ info to translate, as yet */
594566 Assert (subroot .oj_info_list == NIL );
595567
@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root)
612584
613585 subplans = lappend (subplans , subplan );
614586
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+
615590 /* Build target-relations list for the executor */
616591 resultRelations = lappend_int (resultRelations , appinfo -> child_relid );
617592
@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
12011176 */
12021177 if (parse -> limitCount )
12031178 {
1204- est = estimate_expression_value (parse -> limitCount );
1179+ est = estimate_expression_value (root , parse -> limitCount );
12051180 if (est && IsA (est , Const ))
12061181 {
12071182 if (((Const * ) est )-> constisnull )
@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
12241199
12251200 if (parse -> limitOffset )
12261201 {
1227- est = estimate_expression_value (parse -> limitOffset );
1202+ est = estimate_expression_value (root , parse -> limitOffset );
12281203 if (est && IsA (est , Const ))
12291204 {
12301205 if (((Const * ) est )-> constisnull )
0 commit comments