Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f492388

Browse files
committed
Fix calculation of plan node extParams to account for the possibility that one
initPlan sets a parameter for another. This could not (I think) happen before 8.1, but it's possible now because the initPlans generated by MIN/MAX optimization might themselves use initPlans. We attach those initPlans as siblings of the MIN/MAX ones, not children, to avoid duplicate computation when multiple MIN/MAX aggregates are present; so this leads to the case of an initPlan needing the result of a sibling initPlan, which is not possible with ordinary query nesting. Hadn't been noticed because in most contexts having too much stuff listed in extParam is fairly harmless. Fixes "plan should not reference subplan's variable" bug reported by Catalin Pitis.
1 parent e573459 commit f492388

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

src/backend/optimizer/plan/subselect.c

Lines changed: 29 additions & 10 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-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.106 2006/04/28 20:57:49 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.107 2006/05/03 00:24:56 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -912,9 +912,11 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
912912
void
913913
SS_finalize_plan(Plan *plan, List *rtable)
914914
{
915-
Bitmapset *outer_params = NULL;
916-
Bitmapset *valid_params = NULL;
917-
Cost initplan_cost = 0;
915+
Bitmapset *outer_params,
916+
*valid_params,
917+
*initExtParam,
918+
*initSetParam;
919+
Cost initplan_cost;
918920
int paramid;
919921
ListCell *l;
920922

@@ -923,6 +925,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
923925
* available from outer query levels and my own query level. We do this
924926
* once to save time in the per-plan recursion steps.
925927
*/
928+
outer_params = valid_params = NULL;
926929
paramid = 0;
927930
foreach(l, PlannerParamList)
928931
{
@@ -954,7 +957,11 @@ SS_finalize_plan(Plan *plan, List *rtable)
954957

955958
/*
956959
* Finally, attach any initPlans to the topmost plan node, and add their
957-
* extParams to the topmost node's, too.
960+
* extParams to the topmost node's, too. However, any setParams of the
961+
* initPlans should not be present in the topmost node's extParams, only
962+
* in its allParams. (As of PG 8.1, it's possible that some initPlans
963+
* have extParams that are setParams of other initPlans, so we have to
964+
* take care of this situation explicitly.)
958965
*
959966
* We also add the total_cost of each initPlan to the startup cost of the
960967
* top node. This is a conservative overestimate, since in fact each
@@ -963,17 +970,29 @@ SS_finalize_plan(Plan *plan, List *rtable)
963970
plan->initPlan = PlannerInitPlan;
964971
PlannerInitPlan = NIL; /* make sure they're not attached twice */
965972

973+
initExtParam = initSetParam = NULL;
974+
initplan_cost = 0;
966975
foreach(l, plan->initPlan)
967976
{
968977
SubPlan *initplan = (SubPlan *) lfirst(l);
978+
ListCell *l2;
969979

970-
plan->extParam = bms_add_members(plan->extParam,
971-
initplan->plan->extParam);
972-
/* allParam must include all members of extParam */
973-
plan->allParam = bms_add_members(plan->allParam,
974-
plan->extParam);
980+
initExtParam = bms_add_members(initExtParam,
981+
initplan->plan->extParam);
982+
foreach(l2, initplan->setParam)
983+
{
984+
initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
985+
}
975986
initplan_cost += initplan->plan->total_cost;
976987
}
988+
/* allParam must include all these params */
989+
plan->allParam = bms_add_members(plan->allParam, initExtParam);
990+
plan->allParam = bms_add_members(plan->allParam, initSetParam);
991+
/* but extParam shouldn't include any setParams */
992+
initExtParam = bms_del_members(initExtParam, initSetParam);
993+
/* empty test ensures extParam is exactly NULL if it's empty */
994+
if (!bms_is_empty(initExtParam))
995+
plan->extParam = bms_join(plan->extParam, initExtParam);
977996

978997
plan->startup_cost += initplan_cost;
979998
plan->total_cost += initplan_cost;

0 commit comments

Comments
 (0)