diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 635ddb8671614c00f50331673c0e5795b58a8fc7..b5a7e0abe8bdb3dc05237ea94f8583b8a62c10f2 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -390,6 +390,7 @@ extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
 void
 create_lateral_join_info(PlannerInfo *root)
 {
+	Relids		prev_parents PG_USED_FOR_ASSERTS_ONLY = NULL;
 	Index		rti;
 	ListCell   *lc;
 
@@ -609,31 +610,41 @@ create_lateral_join_info(PlannerInfo *root)
 	 * every child anyway, and there's no value in forcing extra
 	 * reparameterize_path() calls.  Similarly, a lateral reference to the
 	 * parent prevents use of otherwise-movable join rels for each child.
+	 *
+	 * It's possible for child rels to have their own children, in which case
+	 * the topmost parent's lateral info must be propagated all the way down.
+	 * This code handles that case correctly so long as append_rel_list has
+	 * entries for child relationships before grandchild relationships, which
+	 * is an okay assumption right now, but we'll need to be careful to
+	 * preserve it.  The assertions below check for incorrect ordering.
 	 */
-	for (rti = 1; rti < root->simple_rel_array_size; rti++)
+	foreach(lc, root->append_rel_list)
 	{
-		RelOptInfo *brel = root->simple_rel_array[rti];
+		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
+		RelOptInfo *parentrel = root->simple_rel_array[appinfo->parent_relid];
+		RelOptInfo *childrel = root->simple_rel_array[appinfo->child_relid];
 
-		if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
+		/*
+		 * If we're processing a subquery of a query with inherited target rel
+		 * (cf. inheritance_planner), append_rel_list may contain entries for
+		 * tables that are not part of the current subquery and hence have no
+		 * RelOptInfo.  Ignore them.  We can ignore dead rels, too.
+		 */
+		if (parentrel == NULL || parentrel->reloptkind == RELOPT_DEADREL)
 			continue;
 
-		if (root->simple_rte_array[rti]->inh)
-		{
-			foreach(lc, root->append_rel_list)
-			{
-				AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
-				RelOptInfo *childrel;
-
-				if (appinfo->parent_relid != rti)
-					continue;
-				childrel = root->simple_rel_array[appinfo->child_relid];
-				Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
-				Assert(childrel->lateral_relids == NULL);
-				childrel->lateral_relids = brel->lateral_relids;
-				Assert(childrel->lateral_referencers == NULL);
-				childrel->lateral_referencers = brel->lateral_referencers;
-			}
-		}
+		/* Verify that children are processed before grandchildren */
+#ifdef USE_ASSERT_CHECKING
+		prev_parents = bms_add_member(prev_parents, appinfo->parent_relid);
+		Assert(!bms_is_member(appinfo->child_relid, prev_parents));
+#endif
+
+		/* OK, propagate info down */
+		Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
+		Assert(childrel->lateral_relids == NULL);
+		childrel->lateral_relids = parentrel->lateral_relids;
+		Assert(childrel->lateral_referencers == NULL);
+		childrel->lateral_referencers = parentrel->lateral_referencers;
 	}
 }