Skip to content

Commit 474de76

Browse files
committed
Mark a query's topmost Paths parallel-unsafe if they will have initPlans.
Andreas Seltenreich found another case where we were being too optimistic about allowing a plan to be considered parallelizable despite it containing initPlans. It seems like the real issue here is that if we know we are going to tack initPlans onto the topmost Plan node for a subquery, we had better mark that subquery's result Paths as not-parallel-safe. That fixes this problem and allows reversion of a kluge (added in commit 7b67a0a and extended in f24cf96) to not trust the parallel_safe flag at top level. Discussion: <874m2w4k5d.fsf@ex.ansel.ydns.eu>
1 parent bf5fe7b commit 474de76

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
326326
* Optionally add a Gather node for testing purposes, provided this is
327327
* actually a safe thing to do. (Note: we assume adding a Material node
328328
* above did not change the parallel safety of the plan, so we can still
329-
* rely on best_path->parallel_safe. However, that flag doesn't account
330-
* for subplans, which we are unable to transmit to workers presently.)
329+
* rely on best_path->parallel_safe.)
331330
*/
332-
if (force_parallel_mode != FORCE_PARALLEL_OFF &&
333-
best_path->parallel_safe &&
334-
glob->subplans == NIL)
331+
if (force_parallel_mode != FORCE_PARALLEL_OFF && best_path->parallel_safe)
335332
{
336333
Gather *gather = makeNode(Gather);
337334

@@ -782,10 +779,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
782779
SS_identify_outer_params(root);
783780

784781
/*
785-
* If any initPlans were created in this query level, increment the
786-
* surviving Paths' costs to account for them. They won't actually get
787-
* attached to the plan tree till create_plan() runs, but we want to be
788-
* sure their costs are included now.
782+
* If any initPlans were created in this query level, adjust the surviving
783+
* Paths' costs and parallel-safety flags to account for them. The
784+
* initPlans won't actually get attached to the plan tree till
785+
* create_plan() runs, but we must include their effects now.
789786
*/
790787
final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
791788
SS_charge_for_initplans(root, final_rel);

src/backend/optimizer/plan/subselect.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,11 +2134,13 @@ SS_identify_outer_params(PlannerInfo *root)
21342134
}
21352135

21362136
/*
2137-
* SS_charge_for_initplans - account for cost of initplans in Path costs
2137+
* SS_charge_for_initplans - account for initplans in Path costs & parallelism
21382138
*
21392139
* If any initPlans have been created in the current query level, they will
21402140
* get attached to the Plan tree created from whichever Path we select from
2141-
* the given rel; so increment all the rel's Paths' costs to account for them.
2141+
* the given rel. Increment all that rel's Paths' costs to account for them,
2142+
* and make sure the paths get marked as parallel-unsafe, since we can't
2143+
* currently transmit initPlans to parallel workers.
21422144
*
21432145
* This is separate from SS_attach_initplans because we might conditionally
21442146
* create more initPlans during create_plan(), depending on which Path we
@@ -2170,14 +2172,15 @@ SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
21702172
}
21712173

21722174
/*
2173-
* Now adjust the costs.
2175+
* Now adjust the costs and parallel_safe flags.
21742176
*/
21752177
foreach(lc, final_rel->pathlist)
21762178
{
21772179
Path *path = (Path *) lfirst(lc);
21782180

21792181
path->startup_cost += initplan_cost;
21802182
path->total_cost += initplan_cost;
2183+
path->parallel_safe = false;
21812184
}
21822185

21832186
/* We needn't do set_cheapest() here, caller will do it */

0 commit comments

Comments
 (0)