diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 2d7e1d84d0..9c85302321 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1287,13 +1287,29 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 	ListCell   *l;
 	List	   *partitioned_rels = NIL;
 	RangeTblEntry *rte;
+	bool		build_partitioned_rels = false;
 
+	/*
+	 * A plain relation will alread have a PartitionedChildRelInfo if it is
+	 * partitioned.  For a subquery RTE, no PartitionedChildRelInfo exists
+	 * yet; we must build one if it is required.
+	 */
 	rte = planner_rt_fetch(rel->relid, root);
-	if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+	switch (rte->rtekind)
 	{
-		partitioned_rels = get_partitioned_child_rels(root, rel->relid);
-		/* The root partitioned table is included as a child rel */
-		Assert(list_length(partitioned_rels) >= 1);
+		case RTE_RELATION:
+			if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+			{
+				partitioned_rels =
+					get_partitioned_child_rels(root, rel->relid);
+				Assert(list_length(partitioned_rels) >= 1);
+			}
+			break;
+		case RTE_SUBQUERY:
+			build_partitioned_rels = true;
+			break;
+		default:
+			elog(ERROR, "unexpcted rtekind: %d", (int) rte->rtekind);
 	}
 
 	/*
@@ -1307,6 +1323,19 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 		ListCell   *lcp;
 
 		/*
+		 * If we need to build partitioned_rels, accumulate the partitioned
+		 * rels for this child.
+		 */
+		if (build_partitioned_rels)
+		{
+			List	   *cprels;
+
+			cprels = get_partitioned_child_rels(root, childrel->relid);
+			partitioned_rels = list_concat(partitioned_rels,
+										   list_copy(cprels));
+		}
+
+		/*
 		 * If child has an unparameterized cheapest-total path, add that to
 		 * the unparameterized Append path we are constructing for the parent.
 		 * If not, there's no workable unparameterized path.
@@ -1390,6 +1419,21 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 	}
 
 	/*
+	 * If our parent is also an appendrel, it will need to build an
+	 * appropriate partitioned_rels list in turn, and that requires that we
+	 * have a PartitionedChildRelInfo.
+	 */
+	if (build_partitioned_rels && partitioned_rels != NIL)
+	{
+		PartitionedChildRelInfo *pcinfo;
+
+		pcinfo = makeNode(PartitionedChildRelInfo);
+		pcinfo->parent_relid = rel->relid;
+		pcinfo->child_rels = partitioned_rels;
+		root->pcinfo_list = lappend(root->pcinfo_list, pcinfo);
+	}
+
+	/*
 	 * If we found unparameterized paths for all children, build an unordered,
 	 * unparameterized Append path for the rel.  (Note: this is correct even
 	 * if we have zero or one live subpath due to constraint exclusion.)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 6b79b3ad99..907622eadb 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6076,7 +6076,8 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
  *		Returns a list of the RT indexes of the partitioned child relations
  *		with rti as the root parent RT index.
  *
- * Note: Only call this function on RTEs known to be partitioned tables.
+ * Note: This function might get called even for range table entries that
+ * are not partitioned tables; in such a case, it will simply return NIL.
  */
 List *
 get_partitioned_child_rels(PlannerInfo *root, Index rti)
@@ -6095,8 +6096,5 @@ get_partitioned_child_rels(PlannerInfo *root, Index rti)
 		}
 	}
 
-	/* The root partitioned table is included as a child rel */
-	Assert(list_length(result) >= 1);
-
 	return result;
 }
