git.postgresql.org Git - postgresql.git/commitdiff

git projects / postgresql.git / commitdiff
? search:
summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 00f0b47)
Fix another thinko in join_is_legal's handling of semijoins: we have to test
2009年7月23日 17:42:06 +0000 (17:42 +0000)
2009年7月23日 17:42:06 +0000 (17:42 +0000)
for the case that the semijoin was implemented within either input by
unique-ifying its RHS before we test to see if it appears to match the current
join situation. The previous coding would select semijoin logic in situations
where we'd already unique-ified the RHS and joined it to some unrelated
relation(s), and then came to join it to the semijoin's LHS. That still gave
the right answer as far as the semijoin itself was concerned, but would lead
to incorrectly examining only an arbitrary one of the matchable rows from the
unrelated relation(s). The cause of this thinko was incorrect unification of
the pre-8.4 logic for IN joins and OUTER joins --- the comparable case for
outer joins can be handled after making the match test, but that's because
there is nothing like the unique-ification escape hatch for outer joins.
Per bug #4934 from Benjamin Reed.


diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 350fde29c21f78cf73d5e89412b6f58bd843c064..49e8a1222aa2351f0b6fc97a0319116b1bfb624b 100644 (file)
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.101 2009年07月19日 20:32:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.102 2009年07月23日 17:42:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -399,6 +399,22 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
bms_is_subset(sjinfo->min_righthand, rel2->relids))
continue;
+ /*
+ * If it's a semijoin and we already joined the RHS to any other
+ * rels within either input, then we must have unique-ified the RHS
+ * at that point (see below). Therefore the semijoin is no longer
+ * relevant in this join path.
+ */
+ if (sjinfo->jointype == JOIN_SEMI)
+ {
+ if (bms_is_subset(sjinfo->syn_righthand, rel1->relids) &&
+ !bms_equal(sjinfo->syn_righthand, rel1->relids))
+ continue;
+ if (bms_is_subset(sjinfo->syn_righthand, rel2->relids) &&
+ !bms_equal(sjinfo->syn_righthand, rel2->relids))
+ continue;
+ }
+
/*
* If one input contains min_lefthand and the other contains
* min_righthand, then we can perform the SJ at this join.
@@ -491,9 +507,6 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
* We assume that make_outerjoininfo() set things up correctly
* so that we'll only match to some SJ if the join is valid.
* Set flag here to check at bottom of loop.
- *
- * For a semijoin, assume it's okay if either side fully contains
- * the RHS (per the unique-ification case above).
*----------
*/
if (sjinfo->jointype != JOIN_SEMI &&
@@ -503,12 +516,6 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
/* seems OK */
Assert(!bms_overlap(joinrelids, sjinfo->min_lefthand));
}
- else if (sjinfo->jointype == JOIN_SEMI &&
- (bms_is_subset(sjinfo->syn_righthand, rel1->relids) ||
- bms_is_subset(sjinfo->syn_righthand, rel2->relids)))
- {
- /* seems OK */
- }
else
is_valid_inner = false;
}
This is the main PostgreSQL git repository.
RSS Atom

AltStyle によって変換されたページ (->オリジナル) /