@@ -88,7 +88,7 @@ static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path,
88
88
int flags );
89
89
static Gather * create_gather_plan (PlannerInfo * root , GatherPath * best_path );
90
90
static Plan * create_projection_plan (PlannerInfo * root , ProjectionPath * best_path );
91
- static Plan * inject_projection_plan (Plan * subplan , List * tlist );
91
+ static Plan * inject_projection_plan (Plan * subplan , List * tlist , bool parallel_safe );
92
92
static Sort * create_sort_plan (PlannerInfo * root , SortPath * best_path , int flags );
93
93
static Group * create_group_plan (PlannerInfo * root , GroupPath * best_path );
94
94
static Unique * create_upper_unique_plan (PlannerInfo * root , UpperUniquePath * best_path ,
@@ -920,6 +920,9 @@ create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
920
920
*/
921
921
copy_plan_costsize (gplan , plan );
922
922
923
+ /* Gating quals could be unsafe, so better use the Path's safety flag */
924
+ gplan -> parallel_safe = path -> parallel_safe ;
925
+
923
926
return gplan ;
924
927
}
925
928
@@ -1313,7 +1316,8 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
1313
1316
*/
1314
1317
if (!is_projection_capable_plan (subplan ) &&
1315
1318
!tlist_same_exprs (newtlist , subplan -> targetlist ))
1316
- subplan = inject_projection_plan (subplan , newtlist );
1319
+ subplan = inject_projection_plan (subplan , newtlist ,
1320
+ best_path -> path .parallel_safe );
1317
1321
else
1318
1322
subplan -> targetlist = newtlist ;
1319
1323
}
@@ -1572,7 +1576,8 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
1572
1576
plan -> total_cost = best_path -> path .total_cost ;
1573
1577
plan -> plan_rows = best_path -> path .rows ;
1574
1578
plan -> plan_width = best_path -> path .pathtarget -> width ;
1575
- /* ... but be careful not to munge subplan's parallel-aware flag */
1579
+ plan -> parallel_safe = best_path -> path .parallel_safe ;
1580
+ /* ... but don't change subplan's parallel_aware flag */
1576
1581
}
1577
1582
else
1578
1583
{
@@ -1592,9 +1597,12 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
1592
1597
* This is used in a few places where we decide on-the-fly that we need a
1593
1598
* projection step as part of the tree generated for some Path node.
1594
1599
* We should try to get rid of this in favor of doing it more honestly.
1600
+ *
1601
+ * One reason it's ugly is we have to be told the right parallel_safe marking
1602
+ * to apply (since the tlist might be unsafe even if the child plan is safe).
1595
1603
*/
1596
1604
static Plan *
1597
- inject_projection_plan (Plan * subplan , List * tlist )
1605
+ inject_projection_plan (Plan * subplan , List * tlist , bool parallel_safe )
1598
1606
{
1599
1607
Plan * plan ;
1600
1608
@@ -1608,6 +1616,7 @@ inject_projection_plan(Plan *subplan, List *tlist)
1608
1616
* consistent not more so. Hence, just copy the subplan's cost.
1609
1617
*/
1610
1618
copy_plan_costsize (plan , subplan );
1619
+ plan -> parallel_safe = parallel_safe ;
1611
1620
1612
1621
return plan ;
1613
1622
}
@@ -1984,6 +1993,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
1984
1993
plan -> plan_rows = 1 ;
1985
1994
plan -> plan_width = mminfo -> path -> pathtarget -> width ;
1986
1995
plan -> parallel_aware = false;
1996
+ plan -> parallel_safe = mminfo -> path -> parallel_safe ;
1987
1997
1988
1998
/* Convert the plan into an InitPlan in the outer query. */
1989
1999
SS_make_initplan_from_plan (root , subroot , plan , mminfo -> param );
@@ -2829,6 +2839,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
2829
2839
clamp_row_est (apath -> bitmapselectivity * apath -> path .parent -> tuples );
2830
2840
plan -> plan_width = 0 ; /* meaningless */
2831
2841
plan -> parallel_aware = false;
2842
+ plan -> parallel_safe = apath -> path .parallel_safe ;
2832
2843
* qual = subquals ;
2833
2844
* indexqual = subindexquals ;
2834
2845
* indexECs = subindexECs ;
@@ -2892,6 +2903,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
2892
2903
clamp_row_est (opath -> bitmapselectivity * opath -> path .parent -> tuples );
2893
2904
plan -> plan_width = 0 ; /* meaningless */
2894
2905
plan -> parallel_aware = false;
2906
+ plan -> parallel_safe = opath -> path .parallel_safe ;
2895
2907
}
2896
2908
2897
2909
/*
@@ -2936,6 +2948,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
2936
2948
clamp_row_est (ipath -> indexselectivity * ipath -> path .parent -> tuples );
2937
2949
plan -> plan_width = 0 ; /* meaningless */
2938
2950
plan -> parallel_aware = false;
2951
+ plan -> parallel_safe = ipath -> path .parallel_safe ;
2939
2952
* qual = get_actual_clauses (ipath -> indexclauses );
2940
2953
* indexqual = get_actual_clauses (ipath -> indexquals );
2941
2954
foreach (l , ipath -> indexinfo -> indpred )
@@ -4834,7 +4847,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses)
4834
4847
/*
4835
4848
* Copy cost and size info from a Path node to the Plan node created from it.
4836
4849
* The executor usually won't use this info, but it's needed by EXPLAIN.
4837
- * Also copy the parallel-aware flag , which the executor *will* use.
4850
+ * Also copy the parallel-related flags , which the executor *will* use.
4838
4851
*/
4839
4852
static void
4840
4853
copy_generic_path_info (Plan * dest , Path * src )
@@ -4844,6 +4857,7 @@ copy_generic_path_info(Plan *dest, Path *src)
4844
4857
dest -> plan_rows = src -> rows ;
4845
4858
dest -> plan_width = src -> pathtarget -> width ;
4846
4859
dest -> parallel_aware = src -> parallel_aware ;
4860
+ dest -> parallel_safe = src -> parallel_safe ;
4847
4861
}
4848
4862
4849
4863
/*
@@ -4859,6 +4873,8 @@ copy_plan_costsize(Plan *dest, Plan *src)
4859
4873
dest -> plan_width = src -> plan_width ;
4860
4874
/* Assume the inserted node is not parallel-aware. */
4861
4875
dest -> parallel_aware = false;
4876
+ /* Assume the inserted node is parallel-safe, if child plan is. */
4877
+ dest -> parallel_safe = src -> parallel_safe ;
4862
4878
}
4863
4879
4864
4880
/*
@@ -4888,6 +4904,7 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
4888
4904
plan -> plan .plan_rows = lefttree -> plan_rows ;
4889
4905
plan -> plan .plan_width = lefttree -> plan_width ;
4890
4906
plan -> plan .parallel_aware = false;
4907
+ plan -> plan .parallel_safe = lefttree -> parallel_safe ;
4891
4908
}
4892
4909
4893
4910
/*
@@ -5696,7 +5713,8 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
5696
5713
{
5697
5714
/* copy needed so we don't modify input's tlist below */
5698
5715
tlist = copyObject (tlist );
5699
- lefttree = inject_projection_plan (lefttree , tlist );
5716
+ lefttree = inject_projection_plan (lefttree , tlist ,
5717
+ lefttree -> parallel_safe );
5700
5718
}
5701
5719
5702
5720
/* Don't bother testing is_projection_capable_plan again */
@@ -5975,6 +5993,7 @@ materialize_finished_plan(Plan *subplan)
5975
5993
matplan -> plan_rows = subplan -> plan_rows ;
5976
5994
matplan -> plan_width = subplan -> plan_width ;
5977
5995
matplan -> parallel_aware = false;
5996
+ matplan -> parallel_safe = subplan -> parallel_safe ;
5978
5997
5979
5998
return matplan ;
5980
5999
}
0 commit comments