diff options
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 5328f19afea..4ab3a6ea42b 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -641,6 +641,20 @@ make_outerjoininfo(PlannerInfo *root, min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels), right_rels); + /* + * If we have a degenerate join clause that doesn't mention any RHS rels, + * force the min RHS to be the syntactic RHS; otherwise we can end up + * making serious errors, like putting the LHS on the wrong side of an + * outer join. It seems to be safe to not do this when we have a + * contribution from inner_join_rels, though; that's enough to pin the SJ + * to occur at a reasonable place in the tree. + */ + if (bms_is_empty(min_righthand)) + min_righthand = bms_copy(right_rels); + + /* + * Now check previous outer joins for ordering restrictions. + */ foreach(l, root->join_info_list) { SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l); @@ -742,12 +756,10 @@ make_outerjoininfo(PlannerInfo *root, * If we found nothing to put in min_lefthand, punt and make it the full * LHS, to avoid having an empty min_lefthand which will confuse later * processing. (We don't try to be smart about such cases, just correct.) - * Likewise for min_righthand. + * We already forced min_righthand nonempty, so nothing to do for that. */ if (bms_is_empty(min_lefthand)) min_lefthand = bms_copy(left_rels); - if (bms_is_empty(min_righthand)) - min_righthand = bms_copy(right_rels); /* Now they'd better be nonempty */ Assert(!bms_is_empty(min_lefthand)); |