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.
This commit is contained in:
parent
e57345975c
commit
f4923880b3
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.106 2006/04/28 20:57:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.107 2006/05/03 00:24:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -912,9 +912,11 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
|
||||
void
|
||||
SS_finalize_plan(Plan *plan, List *rtable)
|
||||
{
|
||||
Bitmapset *outer_params = NULL;
|
||||
Bitmapset *valid_params = NULL;
|
||||
Cost initplan_cost = 0;
|
||||
Bitmapset *outer_params,
|
||||
*valid_params,
|
||||
*initExtParam,
|
||||
*initSetParam;
|
||||
Cost initplan_cost;
|
||||
int paramid;
|
||||
ListCell *l;
|
||||
|
||||
@ -923,6 +925,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
|
||||
* available from outer query levels and my own query level. We do this
|
||||
* once to save time in the per-plan recursion steps.
|
||||
*/
|
||||
outer_params = valid_params = NULL;
|
||||
paramid = 0;
|
||||
foreach(l, PlannerParamList)
|
||||
{
|
||||
@ -954,7 +957,11 @@ SS_finalize_plan(Plan *plan, List *rtable)
|
||||
|
||||
/*
|
||||
* Finally, attach any initPlans to the topmost plan node, and add their
|
||||
* extParams to the topmost node's, too.
|
||||
* extParams to the topmost node's, too. However, any setParams of the
|
||||
* initPlans should not be present in the topmost node's extParams, only
|
||||
* in its allParams. (As of PG 8.1, it's possible that some initPlans
|
||||
* have extParams that are setParams of other initPlans, so we have to
|
||||
* take care of this situation explicitly.)
|
||||
*
|
||||
* We also add the total_cost of each initPlan to the startup cost of the
|
||||
* top node. This is a conservative overestimate, since in fact each
|
||||
@ -963,17 +970,29 @@ SS_finalize_plan(Plan *plan, List *rtable)
|
||||
plan->initPlan = PlannerInitPlan;
|
||||
PlannerInitPlan = NIL; /* make sure they're not attached twice */
|
||||
|
||||
initExtParam = initSetParam = NULL;
|
||||
initplan_cost = 0;
|
||||
foreach(l, plan->initPlan)
|
||||
{
|
||||
SubPlan *initplan = (SubPlan *) lfirst(l);
|
||||
ListCell *l2;
|
||||
|
||||
plan->extParam = bms_add_members(plan->extParam,
|
||||
initplan->plan->extParam);
|
||||
/* allParam must include all members of extParam */
|
||||
plan->allParam = bms_add_members(plan->allParam,
|
||||
plan->extParam);
|
||||
initExtParam = bms_add_members(initExtParam,
|
||||
initplan->plan->extParam);
|
||||
foreach(l2, initplan->setParam)
|
||||
{
|
||||
initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
|
||||
}
|
||||
initplan_cost += initplan->plan->total_cost;
|
||||
}
|
||||
/* allParam must include all these params */
|
||||
plan->allParam = bms_add_members(plan->allParam, initExtParam);
|
||||
plan->allParam = bms_add_members(plan->allParam, initSetParam);
|
||||
/* but extParam shouldn't include any setParams */
|
||||
initExtParam = bms_del_members(initExtParam, initSetParam);
|
||||
/* empty test ensures extParam is exactly NULL if it's empty */
|
||||
if (!bms_is_empty(initExtParam))
|
||||
plan->extParam = bms_join(plan->extParam, initExtParam);
|
||||
|
||||
plan->startup_cost += initplan_cost;
|
||||
plan->total_cost += initplan_cost;
|
||||
|
Loading…
Reference in New Issue
Block a user