summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/planner.c8
-rw-r--r--src/backend/optimizer/plan/setrefs.c9
-rw-r--r--src/backend/optimizer/plan/subselect.c8
-rw-r--r--src/backend/optimizer/util/pathnode.c2
4 files changed, 17 insertions, 10 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a10bb89dcb6..a9d3c22d7ca 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -430,12 +430,10 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Gather *gather = makeNode(Gather);
/*
- * If there are any initPlans attached to the formerly-top plan node,
- * move them up to the Gather node; same as we do for Material node in
- * materialize_finished_plan.
+ * Top plan must not have any initPlans, else it shouldn't have been
+ * marked parallel-safe.
*/
- gather->plan.initPlan = top_plan->initPlan;
- top_plan->initPlan = NIL;
+ Assert(top_plan->initPlan == NIL);
gather->plan.targetlist = top_plan->targetlist;
gather->plan.qual = NIL;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index a6ad28570ac..15ffaa37079 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1102,7 +1102,14 @@ set_subqueryscan_references(PlannerInfo *root,
result = plan->subplan;
- /* We have to be sure we don't lose any initplans */
+ /*
+ * We have to be sure we don't lose any initplans, so move any that
+ * were attached to the parent plan to the child. If we do move any,
+ * the child is no longer parallel-safe.
+ */
+ if (plan->scan.plan.initPlan)
+ result->parallel_safe = false;
+
result->initPlan = list_concat(plan->scan.plan.initPlan,
result->initPlan);
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index b22519e69eb..adada2a1b48 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1879,7 +1879,7 @@ SS_identify_outer_params(PlannerInfo *root)
* This is separate from SS_attach_initplans because we might conditionally
* create more initPlans during create_plan(), depending on which Path we
* select. However, Paths that would generate such initPlans are expected
- * to have included their cost already.
+ * to have included their cost and parallel-safety effects already.
*/
void
SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
@@ -1935,8 +1935,10 @@ SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
* (In principle the initPlans could go in any node at or above where they're
* referenced; but there seems no reason to put them any lower than the
* topmost node, so we don't bother to track exactly where they came from.)
- * We do not touch the plan node's cost; the initplans should have been
- * accounted for in path costing.
+ *
+ * We do not touch the plan node's cost or parallel_safe flag. The initplans
+ * must have been accounted for in SS_charge_for_initplans, or by any later
+ * code that adds initplans via SS_make_initplan_from_plan.
*/
void
SS_attach_initplans(PlannerInfo *root, Plan *plan)
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index aa8f2de72af..24a216e754f 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -3093,7 +3093,7 @@ create_minmaxagg_path(PlannerInfo *root,
/* For now, assume we are above any joins, so no parameterization */
pathnode->path.param_info = NULL;
pathnode->path.parallel_aware = false;
- /* A MinMaxAggPath implies use of subplans, so cannot be parallel-safe */
+ /* A MinMaxAggPath implies use of initplans, so cannot be parallel-safe */
pathnode->path.parallel_safe = false;
pathnode->path.parallel_workers = 0;
/* Result is one unordered row */