aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/joinpath.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-05-01 14:39:11 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-05-01 14:39:11 -0400
commit2057a58d1629ebffce694e3cef7f714571a88dd7 (patch)
treed96a4bc525cc403668ae5984fe940a719639e83b /src/backend/optimizer/path/joinpath.c
parent74a20d0ab7c99b3efcf5dc7aac741e3b2f952a34 (diff)
downloadpostgresql-2057a58d1629ebffce694e3cef7f714571a88dd7.tar.gz
postgresql-2057a58d1629ebffce694e3cef7f714571a88dd7.zip
Fix mis-optimization of semijoins with more than one LHS relation.
The inner-unique patch (commit 9c7f5229a) supposed that if we're considering a JOIN_UNIQUE_INNER join path, we can always set inner_unique for the join, because the inner path produced by create_unique_path should be unique relative to the outer relation. However, that's true only if we're considering joining to the whole outer relation --- otherwise we may be applying only some of the join quals, and so the inner path might be non-unique from the perspective of this join. Adjust the test to only believe that we can set inner_unique if we have the whole semijoin LHS on the outer side. There is more that can be done in this area, but this commit is only intended to provide the minimal fix needed to get correct plans. Per report from Teodor Sigaev. Thanks to David Rowley for preliminary investigation. Discussion: https://postgr.es/m/f994fc98-389f-4a46-d1bc-c42e05cb43ed@sigaev.ru
Diffstat (limited to 'src/backend/optimizer/path/joinpath.c')
-rw-r--r--src/backend/optimizer/path/joinpath.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 5aedcd15411..39e2ddda906 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -126,8 +126,11 @@ add_paths_to_joinrel(PlannerInfo *root,
*
* We have some special cases: for JOIN_SEMI and JOIN_ANTI, it doesn't
* matter since the executor can make the equivalent optimization anyway;
- * we need not expend planner cycles on proofs. For JOIN_UNIQUE_INNER, we
- * know we're going to force uniqueness of the innerrel below. For
+ * we need not expend planner cycles on proofs. For JOIN_UNIQUE_INNER, if
+ * the LHS covers all of the associated semijoin's min_lefthand, then it's
+ * appropriate to set inner_unique because the path produced by
+ * create_unique_path will be unique relative to the LHS. (If we have an
+ * LHS that's only part of the min_lefthand, that is *not* true.) For
* JOIN_UNIQUE_OUTER, pass JOIN_INNER to avoid letting that value escape
* this module.
*/
@@ -138,7 +141,8 @@ add_paths_to_joinrel(PlannerInfo *root,
extra.inner_unique = false; /* well, unproven */
break;
case JOIN_UNIQUE_INNER:
- extra.inner_unique = true;
+ extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
+ outerrel->relids);
break;
case JOIN_UNIQUE_OUTER:
extra.inner_unique = innerrel_is_unique(root, outerrel, innerrel,