@@ -165,8 +165,8 @@ make_one_rel(PlannerInfo *root, List *joinlist)
165165set_base_rel_consider_startup (root );
166166
167167/*
168- *Generate access paths for the base rels. set_base_rel_sizes also sets
169- *the consider_parallel flag for each baserel, if appropriate .
168+ *Compute size estimates and consider_parallel flags for each base rel,
169+ *then generate access paths .
170170 */
171171set_base_rel_sizes (root );
172172set_base_rel_pathlists (root );
@@ -234,7 +234,7 @@ set_base_rel_consider_startup(PlannerInfo *root)
234234 *
235235 * We do this in a separate pass over the base rels so that rowcount
236236 * estimates are available for parameterized path generation, and also so
237- * thatthe consider_parallel flag is set correctly before we begin to
237+ * thateach rel's consider_parallel flag is set correctly before we begin to
238238 * generate paths.
239239 */
240240static void
@@ -262,9 +262,10 @@ set_base_rel_sizes(PlannerInfo *root)
262262/*
263263 * If parallelism is allowable for this query in general, see whether
264264 * it's allowable for this rel in particular. We have to do this
265- * before set_rel_size, because that if this is an inheritance parent,
266- * set_append_rel_size will pass the consider_parallel flag down to
267- * inheritance children.
265+ * before set_rel_size(), because (a) if this rel is an inheritance
266+ * parent, set_append_rel_size() will use and perhaps change the rel's
267+ * consider_parallel flag, and (b) for some RTE types, set_rel_size()
268+ * goes ahead and makes paths immediately.
268269 */
269270if (root -> glob -> parallelModeOK )
270271set_rel_consider_parallel (root ,rel ,rte );
@@ -494,18 +495,24 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
494495
495496/*
496497 * If this relation could possibly be scanned from within a worker, then set
497- * the consider_parallel flag. The flag has previously been initialized to
498- * false, so we just bail out if it becomes clear that we can't safely set it.
498+ * its consider_parallel flag.
499499 */
500500static void
501501set_rel_consider_parallel (PlannerInfo * root ,RelOptInfo * rel ,
502502RangeTblEntry * rte )
503503{
504+ /*
505+ * The flag has previously been initialized to false, so we can just
506+ * return if it becomes clear that we can't safely set it.
507+ */
508+ Assert (!rel -> consider_parallel );
509+
504510/* Don't call this if parallelism is disallowed for the entire query. */
505511Assert (root -> glob -> parallelModeOK );
506512
507- /* Don't call this for non-baserels. */
508- Assert (rel -> reloptkind == RELOPT_BASEREL );
513+ /* This should only be called for baserels and appendrel children. */
514+ Assert (rel -> reloptkind == RELOPT_BASEREL ||
515+ rel -> reloptkind == RELOPT_OTHER_MEMBER_REL );
509516
510517/* Assorted checks based on rtekind. */
511518switch (rte -> rtekind )
@@ -556,6 +563,13 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
556563if (!rel -> fdwroutine -> IsForeignScanParallelSafe (root ,rel ,rte ))
557564return ;
558565}
566+
567+ /*
568+ * There are additional considerations for appendrels, which we'll
569+ * deal with in set_append_rel_size and set_append_rel_pathlist.
570+ * For now, just set consider_parallel based on the rel's own
571+ * quals and targetlist.
572+ */
559573break ;
560574
561575case RTE_SUBQUERY :
@@ -607,8 +621,9 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
607621 * give up on parallelizing access to this relation. We could consider
608622 * instead postponing application of the restricted quals until we're
609623 * above all the parallelism in the plan tree, but it's not clear that
610- * this would be a win in very many cases, and it might be tricky to make
611- * outer join clauses work correctly.
624+ * that would be a win in very many cases, and it might be tricky to make
625+ * outer join clauses work correctly. It would likely break equivalence
626+ * classes, too.
612627 */
613628if (has_parallel_hazard ((Node * )rel -> baserestrictinfo , false))
614629return ;
@@ -965,9 +980,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
965980continue ;
966981}
967982
968- /* Copy consider_parallel flag from parent. */
969- childrel -> consider_parallel = rel -> consider_parallel ;
970-
971983/*
972984 * CE failed, so finish copying/modifying targetlist and join quals.
973985 *
@@ -1007,6 +1019,16 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10071019 * otherrels. So we just leave the child's attr_needed empty.
10081020 */
10091021
1022+ /*
1023+ * If parallelism is allowable for this query in general, see whether
1024+ * it's allowable for this childrel in particular. But if we've
1025+ * already decided the appendrel is not parallel-safe as a whole,
1026+ * there's no point in considering parallelism for this child. For
1027+ * consistency, do this before calling set_rel_size() for the child.
1028+ */
1029+ if (root -> glob -> parallelModeOK && rel -> consider_parallel )
1030+ set_rel_consider_parallel (root ,childrel ,childRTE );
1031+
10101032/*
10111033 * Compute the child's size.
10121034 */
@@ -1023,6 +1045,18 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10231045/* We have at least one live child. */
10241046has_live_children = true;
10251047
1048+ /*
1049+ * If any live child is not parallel-safe, treat the whole appendrel
1050+ * as not parallel-safe. In future we might be able to generate plans
1051+ * in which some children are farmed out to workers while others are
1052+ * not; but we don't have that today, so it's a waste to consider
1053+ * partial paths anywhere in the appendrel unless it's all safe.
1054+ * (Child rels visited before this one will be unmarked in
1055+ * set_append_rel_pathlist().)
1056+ */
1057+ if (!childrel -> consider_parallel )
1058+ rel -> consider_parallel = false;
1059+
10261060/*
10271061 * Accumulate size information from each live child.
10281062 */
@@ -1139,6 +1173,15 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
11391173childRTE = root -> simple_rte_array [childRTindex ];
11401174childrel = root -> simple_rel_array [childRTindex ];
11411175
1176+ /*
1177+ * If set_append_rel_size() decided the parent appendrel was
1178+ * parallel-unsafe at some point after visiting this child rel, we
1179+ * need to propagate the unsafety marking down to the child, so that
1180+ * we don't generate useless partial paths for it.
1181+ */
1182+ if (!rel -> consider_parallel )
1183+ childrel -> consider_parallel = false;
1184+
11421185/*
11431186 * Compute the child's access paths.
11441187 */