aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/joinrels.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/joinrels.c')
-rw-r--r--src/backend/optimizer/path/joinrels.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index b2cc9f07f56..9f0212fad23 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;