7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -1027,11 +1027,12 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
1027
1027
* SS_finalize_plan - do final sublink processing for a completed Plan.
1028
1028
*
1029
1029
* 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.)
1032
1033
*/
1033
1034
void
1034
- SS_finalize_plan (PlannerInfo * root , Plan * plan )
1035
+ SS_finalize_plan (PlannerInfo * root , Plan * plan , bool attach_initplans )
1035
1036
{
1036
1037
Bitmapset * valid_params ,
1037
1038
* initExtParam ,
@@ -1041,14 +1042,45 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
1041
1042
ListCell * l ;
1042
1043
1043
1044
/*
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.
1050
1082
*/
1051
- valid_params = NULL ;
1083
+ valid_params = bms_copy ( initSetParam ) ;
1052
1084
paramid = 0 ;
1053
1085
foreach (l , root -> glob -> paramlist )
1054
1086
{
@@ -1059,12 +1091,6 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
1059
1091
/* valid outer-level parameter */
1060
1092
valid_params = bms_add_member (valid_params , paramid );
1061
1093
}
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
- }
1068
1094
1069
1095
paramid ++ ;
1070
1096
}
@@ -1088,37 +1114,25 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan)
1088
1114
* top node. This is a conservative overestimate, since in fact each
1089
1115
* initPlan might be executed later than plan startup, or even not at all.
1090
1116
*/
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 )
1097
1118
{
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 ;
1108
1135
}
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 ;
1122
1136
}
1123
1137
1124
1138
/*
@@ -1412,29 +1426,22 @@ Param *
1412
1426
SS_make_initplan_from_plan (PlannerInfo * root , Plan * plan ,
1413
1427
Oid resulttype , int32 resulttypmod )
1414
1428
{
1415
- List * saved_init_plans ;
1416
1429
SubPlan * node ;
1417
1430
Param * prm ;
1418
1431
1419
1432
/*
1420
1433
* 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.)
1427
1439
*/
1428
- saved_init_plans = root -> init_plans ;
1429
- root -> init_plans = NIL ;
1430
1440
1431
1441
/*
1432
1442
* Build extParam/allParam sets for plan nodes.
1433
1443
*/
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);
1438
1445
1439
1446
/*
1440
1447
* Add the subplan and its rtable to the global lists.
@@ -1446,6 +1453,8 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
1446
1453
1447
1454
/*
1448
1455
* 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).
1449
1458
*/
1450
1459
node = makeNode (SubPlan );
1451
1460
node -> subLinkType = EXPR_SUBLINK ;
0 commit comments