diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index b2cc9f07f56d05751bfde08d7a83dcabeb4575a3..9f0212fad23b0cefc05ee7a8c8d5a038206defe4 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -334,6 +334,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 	bool		must_be_leftjoin;
 	bool		lateral_fwd;
 	bool		lateral_rev;
+	Relids		join_lateral_rels;
 	ListCell   *l;
 
 	/*
@@ -569,6 +570,35 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		}
 	}
 
+	/*
+	 * LATERAL references could also cause problems later on if we accept this
+	 * join: if the join's minimum parameterization includes any rels that
+	 * would have to be on the inside of an outer join with this join rel,
+	 * then it's never going to be possible to build the complete query using
+	 * this join.  We should reject this join not only because it'll save
+	 * work, but because if we don't, the clauseless-join heuristics might
+	 * think that legality of this join means that some other join rel need
+	 * not be formed, and that could lead to failure to find any plan at all.
+	 * It seems best not to merge this check into the main loop above, because
+	 * it is concerned with SJs that are not otherwise relevant to this join.
+	 */
+	join_lateral_rels = min_join_parameterization(root, joinrelids);
+	if (join_lateral_rels)
+	{
+		foreach(l, root->join_info_list)
+		{
+			SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
+
+			if (bms_overlap(sjinfo->min_righthand, join_lateral_rels) &&
+				bms_overlap(sjinfo->min_lefthand, joinrelids))
+				return false;	/* will not be able to join to min_righthand */
+			if (sjinfo->jointype == JOIN_FULL &&
+				bms_overlap(sjinfo->min_lefthand, join_lateral_rels) &&
+				bms_overlap(sjinfo->min_righthand, joinrelids))
+				return false;	/* will not be able to join to min_lefthand */
+		}
+	}
+
 	/* Otherwise, it's a valid join */
 	*sjinfo_p = match_sjinfo;
 	*reversed_p = reversed;
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 996b7fe513615f9ff5f74b36717ef0b7e2009455..8cc7bd771b32f5d466f1e18889ec387a852982e6 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -499,6 +499,47 @@ build_join_rel(PlannerInfo *root,
 	return joinrel;
 }
 
+/*
+ * min_join_parameterization
+ *
+ * Determine the minimum possible parameterization of a joinrel, that is, the
+ * set of other rels it contains LATERAL references to.  We save this value in
+ * the join's RelOptInfo.  This function is split out of build_join_rel()
+ * because join_is_legal() needs the value to check a prospective join.
+ */
+Relids
+min_join_parameterization(PlannerInfo *root, Relids joinrelids)
+{
+	Relids		result;
+	ListCell   *lc;
+
+	/* Easy if there are no lateral references */
+	if (root->lateral_info_list == NIL)
+		return NULL;
+
+	/*
+	 * Scan lateral_info_list to find all the lateral references occurring in
+	 * or below this join.
+	 */
+	result = NULL;
+	foreach(lc, root->lateral_info_list)
+	{
+		LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
+
+		if (bms_is_subset(ljinfo->lateral_rhs, joinrelids))
+			result = bms_add_members(result, ljinfo->lateral_lhs);
+	}
+
+	/* Remove any rels that are already included in the join */
+	result = bms_del_members(result, joinrelids);
+
+	/* Maintain invariant that result is exactly NULL if empty */
+	if (bms_is_empty(result))
+		result = NULL;
+
+	return result;
+}
+
 /*
  * build_joinrel_tlist
  *	  Builds a join relation's target list from an input relation.
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index f28b4e2b06330ac4e07360900e8849dd328f97c6..eea75d0d1ec20bb747c5a4aadb429b35c784391f 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -147,6 +147,7 @@ extern RelOptInfo *build_join_rel(PlannerInfo *root,
 			   RelOptInfo *inner_rel,
 			   SpecialJoinInfo *sjinfo,
 			   List **restrictlist_ptr);
+extern Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids);
 extern RelOptInfo *build_empty_join_rel(PlannerInfo *root);
 extern AppendRelInfo *find_childrel_appendrelinfo(PlannerInfo *root,
 							RelOptInfo *rel);
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index f8a9f3f264b2e35466b327c65ad62d3c0cbcc8db..dba5d2dbab383c2e4578fea12324982bd279ceb1 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -3579,6 +3579,47 @@ select * from
  doh! | 123 | 456 | hi de ho neighbor |   
 (2 rows)
 
+--
+-- test for appropriate join order in the presence of lateral references
+--
+explain (verbose, costs off)
+select * from
+  text_tbl t1
+  left join int8_tbl i8
+  on i8.q2 = 123,
+  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
+where t1.f1 = ss.f1;
+                    QUERY PLAN                    
+--------------------------------------------------
+ Nested Loop
+   Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1
+   Join Filter: (t1.f1 = t2.f1)
+   ->  Nested Loop Left Join
+         Output: t1.f1, i8.q1, i8.q2
+         ->  Seq Scan on public.text_tbl t1
+               Output: t1.f1
+         ->  Materialize
+               Output: i8.q1, i8.q2
+               ->  Seq Scan on public.int8_tbl i8
+                     Output: i8.q1, i8.q2
+                     Filter: (i8.q2 = 123)
+   ->  Limit
+         Output: (i8.q1), t2.f1
+         ->  Seq Scan on public.text_tbl t2
+               Output: i8.q1, t2.f1
+(16 rows)
+
+select * from
+  text_tbl t1
+  left join int8_tbl i8
+  on i8.q2 = 123,
+  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
+where t1.f1 = ss.f1;
+  f1  |        q1        | q2  |        q1        |  f1  
+------+------------------+-----+------------------+------
+ doh! | 4567890123456789 | 123 | 4567890123456789 | doh!
+(1 row)
+
 --
 -- test ability to push constants through outer join clauses
 --
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 528e1ef97088d81f53355bf716d6c049fb36c288..fdd4e78cf281da3a009fcc5b1daebceef2aabf5a 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -1115,6 +1115,25 @@ select * from
   left join int4_tbl i4
   on i8.q1 = i4.f1;
 
+--
+-- test for appropriate join order in the presence of lateral references
+--
+
+explain (verbose, costs off)
+select * from
+  text_tbl t1
+  left join int8_tbl i8
+  on i8.q2 = 123,
+  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
+where t1.f1 = ss.f1;
+
+select * from
+  text_tbl t1
+  left join int8_tbl i8
+  on i8.q2 = 123,
+  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
+where t1.f1 = ss.f1;
+
 --
 -- test ability to push constants through outer join clauses
 --