diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index e6a0f8dab6db311b816b2c139eb5dbc343e181ee..1a01ae9b70eb8f4b7f9bb46c83992a444fefcd70 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -178,25 +178,59 @@ join_search_one_level(PlannerInfo *root, int level)
 	}
 
 	/*----------
-	 * Normally, we should always have made at least one join of the current
-	 * level.  However, when special joins are involved, there may be no legal
-	 * way to make an N-way join for some values of N.	For example consider
+	 * Last-ditch effort: if we failed to find any usable joins so far, force
+	 * a set of cartesian-product joins to be generated.  This handles the
+	 * special case where all the available rels have join clauses but we
+	 * cannot use any of those clauses yet.  This can only happen when we are
+	 * considering a join sub-problem (a sub-joinlist) and all the rels in the
+	 * sub-problem have only join clauses with rels outside the sub-problem.
+	 * An example is
 	 *
-	 * SELECT ... FROM t1 WHERE
-	 *	 x IN (SELECT ... FROM t2,t3 WHERE ...) AND
-	 *	 y IN (SELECT ... FROM t4,t5 WHERE ...)
+	 *		SELECT ... FROM a INNER JOIN b ON TRUE, c, d, ...
+	 *		WHERE a.w = c.x and b.y = d.z;
 	 *
-	 * We will flatten this query to a 5-way join problem, but there are
-	 * no 4-way joins that join_is_legal() will consider legal.  We have
-	 * to accept failure at level 4 and go on to discover a workable
-	 * bushy plan at level 5.
-	 *
-	 * However, if there are no special joins then join_is_legal() should
-	 * never fail, and so the following sanity check is useful.
+	 * If the "a INNER JOIN b" sub-problem does not get flattened into the
+	 * upper level, we must be willing to make a cartesian join of a and b;
+	 * but the code above will not have done so, because it thought that both
+	 * a and b have joinclauses.  We consider only left-sided and right-sided
+	 * cartesian joins in this case (no bushy).
 	 *----------
 	 */
-	if (joinrels[level] == NIL && root->join_info_list == NIL)
-		elog(ERROR, "failed to build any %d-way joins", level);
+	if (joinrels[level] == NIL)
+	{
+		/*
+		 * This loop is just like the first one, except we always call
+		 * make_rels_by_clauseless_joins().
+		 */
+		foreach(r, joinrels[level - 1])
+		{
+			RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
+
+			make_rels_by_clauseless_joins(root,
+										  old_rel,
+										  list_head(joinrels[1]));
+		}
+
+		/*----------
+		 * When special joins are involved, there may be no legal way
+		 * to make an N-way join for some values of N.	For example consider
+		 *
+		 * SELECT ... FROM t1 WHERE
+		 *	 x IN (SELECT ... FROM t2,t3 WHERE ...) AND
+		 *	 y IN (SELECT ... FROM t4,t5 WHERE ...)
+		 *
+		 * We will flatten this query to a 5-way join problem, but there are
+		 * no 4-way joins that join_is_legal() will consider legal.  We have
+		 * to accept failure at level 4 and go on to discover a workable
+		 * bushy plan at level 5.
+		 *
+		 * However, if there are no special joins then join_is_legal() should
+		 * never fail, and so the following sanity check is useful.
+		 *----------
+		 */
+		if (joinrels[level] == NIL && root->join_info_list == NIL)
+			elog(ERROR, "failed to build any %d-way joins", level);
+	}
 }
 
 /*
@@ -724,6 +758,13 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
  * could be merged with that function, but it seems clearer to separate the
  * two concerns.  We need this test because there are degenerate cases where
  * a clauseless join must be performed to satisfy join-order restrictions.
+ *
+ * Note: this is only a problem if one side of a degenerate outer join
+ * contains multiple rels, or a clauseless join is required within an
+ * IN/EXISTS RHS; else we will find a join path via the "last ditch" case in
+ * join_search_one_level().  We could dispense with this test if we were
+ * willing to try bushy plans in the "last ditch" case, but that seems much
+ * less efficient.
  */
 bool
 have_join_order_restriction(PlannerInfo *root,