1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Undo mistaken tightening in join_is_legal().

One of the changes I made in commit 8703059c6b turns out not to have
been such a good idea: we still need the exception in join_is_legal() that
allows a join if both inputs already overlap the RHS of the special join
we're checking.  Otherwise we can miss valid plans, and might indeed fail
to find a plan at all, as in recent report from Andreas Seltenreich.

That code was added way back in commit c17117649b, but I failed to
include a regression test case then; my bad.  Put it back with a better
explanation, and a test this time.  The logic does end up a bit different
than before though: I now believe it's appropriate to make this check
first, thereby allowing such a case whether or not we'd consider the
previous SJ(s) to commute with this one.  (Presumably, we already decided
they did; but it was confusing to have this consideration in the middle
of the code that was handling the other case.)

Back-patch to all active branches, like the previous patch.
This commit is contained in:
Tom Lane
2015-08-12 21:18:45 -04:00
parent ccc4c07499
commit cfe30a72fa
3 changed files with 89 additions and 5 deletions

View File

@ -470,11 +470,30 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
{
/*
* Otherwise, the proposed join overlaps the RHS but isn't a valid
* implementation of this SJ. It might still be a legal join,
* however, if we're allowed to associate it into the RHS of this
* SJ. That means this SJ must be a LEFT join (not SEMI or ANTI,
* and certainly not FULL) and the proposed join must not overlap
* the LHS.
* implementation of this SJ. But don't panic quite yet: the RHS
* violation might have occurred previously, in one or both input
* relations, in which case we must have previously decided that
* it was OK to commute some other SJ with this one. If we need
* to perform this join to finish building up the RHS, rejecting
* it could lead to not finding any plan at all. (This can occur
* because of the heuristics elsewhere in this file that postpone
* clauseless joins: we might not consider doing a clauseless join
* within the RHS until after we've performed other, validly
* commutable SJs with one or both sides of the clauseless join.)
* This consideration boils down to the rule that if both inputs
* overlap the RHS, we can allow the join --- they are either
* fully within the RHS, or represent previously-allowed joins to
* rels outside it.
*/
if (bms_overlap(rel1->relids, sjinfo->min_righthand) &&
bms_overlap(rel2->relids, sjinfo->min_righthand))
continue; /* assume valid previous violation of RHS */
/*
* The proposed join could still be legal, but only if we're
* allowed to associate it into the RHS of this SJ. That means
* this SJ must be a LEFT join (not SEMI or ANTI, and certainly
* not FULL) and the proposed join must not overlap the LHS.
*/
if (sjinfo->jointype != JOIN_LEFT ||
bms_overlap(joinrelids, sjinfo->min_lefthand))