diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index f087ddb61db8ae75781b674ba8f9cafb37621346..4a82636734e9415aab262d8deb6ebfc743369328 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1287,13 +1287,34 @@ 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 already have a PartitionedChildRelInfo if it is
+	 * partitioned.  For a subquery RTE, no PartitionedChildRelInfo exists; we
+	 * collect all partitioned_rels associated with any child.  (This assumes
+	 * that we don't need to look through multiple levels of subquery RTEs; if
+	 * we ever do, we could create a PartitionedChildRelInfo with the
+	 * accumulated list of partitioned_rels which would then be found when
+	 * populated our parent rel with paths.  For the present, that appears to
+	 * be unnecessary.)
+	 */
 	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);
 	}
 
 	/*
@@ -1306,6 +1327,19 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
 		RelOptInfo *childrel = lfirst(l);
 		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.
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 3e93eee6d8eb0e9130acce5f8e13ccd0a1f6bb7d..793242759d19335691664faf3a2838881e628f1f 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6068,7 +6068,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)
@@ -6087,8 +6088,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;
 }