diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index d6ffa78..22a6da3 100644
*** a/src/backend/optimizer/plan/initsplan.c
--- b/src/backend/optimizer/plan/initsplan.c
*************** void
*** 419,424 ****
--- 419,425 ----
  create_lateral_join_info(PlannerInfo *root)
  {
  	bool		found_laterals = false;
+ 	Relids		prev_parents PG_USED_FOR_ASSERTS_ONLY = NULL;
  	Index		rti;
  	ListCell   *lc;
  
*************** create_lateral_join_info(PlannerInfo *ro
*** 627,679 ****
  	 * 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.
  	 */
! 	for (rti = 1; rti < root->simple_rel_array_size; rti++)
  	{
! 		RelOptInfo *brel = root->simple_rel_array[rti];
! 		RangeTblEntry *brte = root->simple_rte_array[rti];
! 
! 		/*
! 		 * Skip empty slots. Also skip non-simple relations i.e. dead
! 		 * relations.
! 		 */
! 		if (brel == NULL || !IS_SIMPLE_REL(brel))
! 			continue;
  
  		/*
! 		 * In the case of table inheritance, the parent RTE is directly linked
! 		 * to every child table via an AppendRelInfo.  In the case of table
! 		 * partitioning, the inheritance hierarchy is expanded one level at a
! 		 * time rather than flattened.  Therefore, an other member rel that is
! 		 * a partitioned table may have children of its own, and must
! 		 * therefore be marked with the appropriate lateral info so that those
! 		 * children eventually get marked also.
  		 */
! 		Assert(brte);
! 		if (brel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
! 			(brte->rtekind != RTE_RELATION ||
! 			 brte->relkind != RELKIND_PARTITIONED_TABLE))
  			continue;
  
! 		if (brte->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->direct_lateral_relids == NULL);
! 				childrel->direct_lateral_relids = brel->direct_lateral_relids;
! 				Assert(childrel->lateral_relids == NULL);
! 				childrel->lateral_relids = brel->lateral_relids;
! 				Assert(childrel->lateral_referencers == NULL);
! 				childrel->lateral_referencers = brel->lateral_referencers;
! 			}
! 		}
  	}
  }
  
--- 628,667 ----
  	 * 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.
  	 */
! 	foreach(lc, root->append_rel_list)
  	{
! 		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
! 		RelOptInfo *parentrel = root->simple_rel_array[appinfo->parent_relid];
! 		RelOptInfo *childrel = root->simple_rel_array[appinfo->child_relid];
  
  		/*
! 		 * Apparently append_rel_list can contain bogus parent rels nowadays
  		 */
! 		if (parentrel == NULL)
  			continue;
  
! 		/* 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->direct_lateral_relids == NULL);
! 		childrel->direct_lateral_relids = parentrel->direct_lateral_relids;
! 		Assert(childrel->lateral_relids == NULL);
! 		childrel->lateral_relids = parentrel->lateral_relids;
! 		Assert(childrel->lateral_referencers == NULL);
! 		childrel->lateral_referencers = parentrel->lateral_referencers;
  	}
  }
  
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index f04c6b7..4130514 100644
*** a/src/backend/optimizer/util/relnode.c
--- b/src/backend/optimizer/util/relnode.c
*************** get_baserel_parampathinfo(PlannerInfo *r
*** 1225,1230 ****
--- 1225,1233 ----
  	double		rows;
  	ListCell   *lc;
  
+ 	/* If rel has LATERAL refs, every path for it should account for them */
+ 	Assert(bms_is_subset(baserel->lateral_relids, required_outer));
+ 
  	/* Unparameterized paths have no ParamPathInfo */
  	if (bms_is_empty(required_outer))
  		return NULL;
*************** get_joinrel_parampathinfo(PlannerInfo *r
*** 1320,1325 ****
--- 1323,1331 ----
  	double		rows;
  	ListCell   *lc;
  
+ 	/* If rel has LATERAL refs, every path for it should account for them */
+ 	Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
+ 
  	/* Unparameterized paths have no ParamPathInfo or extra join clauses */
  	if (bms_is_empty(required_outer))
  		return NULL;
*************** get_appendrel_parampathinfo(RelOptInfo *
*** 1511,1516 ****
--- 1517,1525 ----
  {
  	ParamPathInfo *ppi;
  
+ 	/* If rel has LATERAL refs, every path for it should account for them */
+ 	Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
+ 
  	/* Unparameterized paths have no ParamPathInfo */
  	if (bms_is_empty(required_outer))
  		return NULL;
