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

Commit eaf1b5d

Browse files
committed
Tighten up SS_finalize_plan's computation of valid_params to exclude Params of
the current query level that aren't in fact output parameters of the current initPlans. (This means, for example, output parameters of regular subplans.) To make this work correctly for output parameters coming from sibling initplans requires rejiggering the API of SS_finalize_plan just a bit: we need the siblings to be visible to it, rather than hidden as SS_make_initplan_from_plan had been doing. This is really part of my response to bug #4290, but I concluded this part probably shouldn't be back-patched, since all that it's doing is to make a debugging cross-check tighter.
1 parent 772a6d4 commit eaf1b5d

File tree

4 files changed

+76
-69
lines changed

4 files changed

+76
-69
lines changed

src/backend/optimizer/plan/planagg.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.40 2008/07/10 01:17:29 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.41 2008/07/10 02:14:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -486,7 +486,6 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
486486
*/
487487
memcpy(&subroot, root, sizeof(PlannerInfo));
488488
subroot.parse = subparse = (Query *) copyObject(root->parse);
489-
subroot.init_plans = NIL;
490489
subparse->commandType = CMD_SELECT;
491490
subparse->resultRelation = 0;
492491
subparse->returningList = NIL;
@@ -564,11 +563,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
564563
-1);
565564

566565
/*
567-
* Make sure the InitPlan gets into the outer list. It has to appear
568-
* after any other InitPlans it might depend on, too (see comments in
569-
* ExecReScan).
566+
* Put the updated list of InitPlans back into the outer PlannerInfo.
570567
*/
571-
root->init_plans = list_concat(root->init_plans, subroot.init_plans);
568+
root->init_plans = subroot.init_plans;
572569
}
573570

574571
/*

src/backend/optimizer/plan/planner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.233 2008/05/02 21:26:09 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.234 2008/07/10 02:14:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -459,7 +459,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
459459
*/
460460
if (list_length(glob->subplans) != num_old_subplans ||
461461
root->query_level > 1)
462-
SS_finalize_plan(root, plan);
462+
SS_finalize_plan(root, plan, true);
463463

464464
/* Return internal info if caller wants it */
465465
if (subroot)

src/backend/optimizer/plan/subselect.c

Lines changed: 68 additions & 59 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.131 2008/07/10 01:17:29 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.132 2008/07/10 02:14:03 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1027,11 +1027,12 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
10271027
* SS_finalize_plan - do final sublink processing for a completed Plan.
10281028
*
10291029
* This recursively computes the extParam and allParam sets for every Plan
1030-
* node in the given plan tree. It also attaches any generated InitPlans
1031-
* to the top plan node.
1030+
* node in the given plan tree. It also optionally attaches any previously
1031+
* generated InitPlans to the top plan node. (Any InitPlans should already
1032+
* have been put through SS_finalize_plan.)
10321033
*/
10331034
void
1034-
SS_finalize_plan(PlannerInfo *root, Plan *plan)
1035+
SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
10351036
{
10361037
Bitmapset *valid_params,
10371038
*initExtParam,
@@ -1041,14 +1042,45 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
10411042
ListCell *l;
10421043

10431044
/*
1044-
* First, scan the param list to discover the sets of params that are
1045-
* available from outer query levels and my own query level. We do this
1046-
* once to save time in the per-plan recursion steps. (This calculation
1047-
* is overly generous: it can include a lot of params that actually
1048-
* shouldn't be referenced here. However, valid_params is just used as
1049-
* a debugging crosscheck, so it's not worth trying to be exact.)
1045+
* Examine any initPlans to determine the set of external params they
1046+
* reference, the set of output params they supply, and their total cost.
1047+
* We'll use at least some of this info below. (Note we are assuming that
1048+
* finalize_plan doesn't touch the initPlans.)
1049+
*
1050+
* In the case where attach_initplans is false, we are assuming that the
1051+
* existing initPlans are siblings that might supply params needed by the
1052+
* current plan.
1053+
*/
1054+
initExtParam = initSetParam = NULL;
1055+
initplan_cost = 0;
1056+
foreach(l, root->init_plans)
1057+
{
1058+
SubPlan *initsubplan = (SubPlan *) lfirst(l);
1059+
Plan *initplan = planner_subplan_get_plan(root, initsubplan);
1060+
ListCell *l2;
1061+
1062+
initExtParam = bms_add_members(initExtParam, initplan->extParam);
1063+
foreach(l2, initsubplan->setParam)
1064+
{
1065+
initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
1066+
}
1067+
initplan_cost += get_initplan_cost(root, initsubplan);
1068+
}
1069+
1070+
/*
1071+
* Now determine the set of params that are validly referenceable in this
1072+
* query level; to wit, those available from outer query levels plus the
1073+
* output parameters of any initPlans. (We do not include output
1074+
* parameters of regular subplans. Those should only appear within the
1075+
* testexpr of SubPlan nodes, and are taken care of locally within
1076+
* finalize_primnode.)
1077+
*
1078+
* Note: this is a bit overly generous since some parameters of upper
1079+
* query levels might belong to query subtrees that don't include this
1080+
* query. However, valid_params is only a debugging crosscheck, so it
1081+
* doesn't seem worth expending lots of cycles to try to be exact.
10501082
*/
1051-
valid_params = NULL;
1083+
valid_params = bms_copy(initSetParam);
10521084
paramid = 0;
10531085
foreach(l, root->glob->paramlist)
10541086
{
@@ -1059,12 +1091,6 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
10591091
/* valid outer-level parameter */
10601092
valid_params = bms_add_member(valid_params, paramid);
10611093
}
1062-
else if (pitem->abslevel == root->query_level &&
1063-
IsA(pitem->item, Param))
1064-
{
1065-
/* valid local parameter (i.e., a setParam of my child) */
1066-
valid_params = bms_add_member(valid_params, paramid);
1067-
}
10681094

10691095
paramid++;
10701096
}
@@ -1088,37 +1114,25 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
10881114
* top node. This is a conservative overestimate, since in fact each
10891115
* initPlan might be executed later than plan startup, or even not at all.
10901116
*/
1091-
plan->initPlan = root->init_plans;
1092-
root->init_plans = NIL; /* make sure they're not attached twice */
1093-
1094-
initExtParam = initSetParam = NULL;
1095-
initplan_cost = 0;
1096-
foreach(l, plan->initPlan)
1117+
if (attach_initplans)
10971118
{
1098-
SubPlan *initsubplan = (SubPlan *) lfirst(l);
1099-
Plan *initplan = planner_subplan_get_plan(root, initsubplan);
1100-
ListCell *l2;
1101-
1102-
initExtParam = bms_add_members(initExtParam, initplan->extParam);
1103-
foreach(l2, initsubplan->setParam)
1104-
{
1105-
initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
1106-
}
1107-
initplan_cost += get_initplan_cost(root, initsubplan);
1119+
plan->initPlan = root->init_plans;
1120+
root->init_plans = NIL; /* make sure they're not attached twice */
1121+
1122+
/* allParam must include all these params */
1123+
plan->allParam = bms_add_members(plan->allParam, initExtParam);
1124+
plan->allParam = bms_add_members(plan->allParam, initSetParam);
1125+
/* extParam must include any child extParam */
1126+
plan->extParam = bms_add_members(plan->extParam, initExtParam);
1127+
/* but extParam shouldn't include any setParams */
1128+
plan->extParam = bms_del_members(plan->extParam, initSetParam);
1129+
/* ensure extParam is exactly NULL if it's empty */
1130+
if (bms_is_empty(plan->extParam))
1131+
plan->extParam = NULL;
1132+
1133+
plan->startup_cost += initplan_cost;
1134+
plan->total_cost += initplan_cost;
11081135
}
1109-
/* allParam must include all these params */
1110-
plan->allParam = bms_add_members(plan->allParam, initExtParam);
1111-
plan->allParam = bms_add_members(plan->allParam, initSetParam);
1112-
/* extParam must include any child extParam */
1113-
plan->extParam = bms_add_members(plan->extParam, initExtParam);
1114-
/* but extParam shouldn't include any setParams */
1115-
plan->extParam = bms_del_members(plan->extParam, initSetParam);
1116-
/* ensure extParam is exactly NULL if it's empty */
1117-
if (bms_is_empty(plan->extParam))
1118-
plan->extParam = NULL;
1119-
1120-
plan->startup_cost += initplan_cost;
1121-
plan->total_cost += initplan_cost;
11221136
}
11231137

11241138
/*
@@ -1412,29 +1426,22 @@ Param *
14121426
SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
14131427
Oid resulttype, int32 resulttypmod)
14141428
{
1415-
List *saved_init_plans;
14161429
SubPlan *node;
14171430
Param *prm;
14181431

14191432
/*
14201433
* We must run SS_finalize_plan(), since that's normally done before a
1421-
* subplan gets put into the initplan list. However it will try to attach
1422-
* any pre-existing initplans to this one, which we don't want (they are
1423-
* siblings not children of this initplan). So, a quick kluge to hide
1424-
* them. (This is something else that could perhaps be cleaner if we did
1425-
* extParam/allParam processing in setrefs.c instead of here? See notes
1426-
* for materialize_finished_plan.)
1434+
* subplan gets put into the initplan list. Tell it not to attach any
1435+
* pre-existing initplans to this one, since they are siblings not
1436+
* children of this initplan. (This is something else that could perhaps
1437+
* be cleaner if we did extParam/allParam processing in setrefs.c instead
1438+
* of here? See notes for materialize_finished_plan.)
14271439
*/
1428-
saved_init_plans = root->init_plans;
1429-
root->init_plans = NIL;
14301440

14311441
/*
14321442
* Build extParam/allParam sets for plan nodes.
14331443
*/
1434-
SS_finalize_plan(root, plan);
1435-
1436-
/* Restore outer initplan list */
1437-
root->init_plans = saved_init_plans;
1444+
SS_finalize_plan(root, plan, false);
14381445

14391446
/*
14401447
* Add the subplan and its rtable to the global lists.
@@ -1446,6 +1453,8 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
14461453

14471454
/*
14481455
* Create a SubPlan node and add it to the outer list of InitPlans.
1456+
* Note it has to appear after any other InitPlans it might depend on
1457+
* (see comments in ExecReScan).
14491458
*/
14501459
node = makeNode(SubPlan);
14511460
node->subLinkType = EXPR_SUBLINK;

src/include/optimizer/subselect.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.30 2008/01/01 19:45:58 momjian Exp $
8+
* $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.31 2008/07/10 02:14:03 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -18,7 +18,8 @@
1818
extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink);
1919
extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
2020
extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
21-
extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
21+
extern void SS_finalize_plan(PlannerInfo *root, Plan *plan,
22+
bool attach_initplans);
2223
extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
2324
Oid resulttype, int32 resulttypmod);
2425

0 commit comments

Comments
 (0)