aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/joinrels.c15
-rw-r--r--src/test/regress/expected/join.out14
-rw-r--r--src/test/regress/sql/join.sql10
3 files changed, 36 insertions, 3 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 9e6f57f4c9e..350fde29c21 100644
--- 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.100 2009/06/11 14:48:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.101 2009/07/19 20:32:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -349,6 +349,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
{
SpecialJoinInfo *match_sjinfo;
bool reversed;
+ bool unique_ified;
bool is_valid_inner;
ListCell *l;
@@ -366,6 +367,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
*/
match_sjinfo = NULL;
reversed = false;
+ unique_ified = false;
is_valid_inner = true;
foreach(l, root->join_info_list)
@@ -450,6 +452,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
return false; /* invalid join path */
match_sjinfo = sjinfo;
reversed = false;
+ unique_ified = true;
}
else if (sjinfo->jointype == JOIN_SEMI &&
bms_equal(sjinfo->syn_righthand, rel1->relids) &&
@@ -461,6 +464,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
return false; /* invalid join path */
match_sjinfo = sjinfo;
reversed = true;
+ unique_ified = true;
}
else
{
@@ -510,8 +514,13 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
}
}
- /* Fail if violated some SJ's RHS and didn't match to another SJ */
- if (match_sjinfo == NULL && !is_valid_inner)
+ /*
+ * Fail if violated some SJ's RHS and didn't match to another SJ.
+ * However, "matching" to a semijoin we are implementing by
+ * unique-ification doesn't count (think: it's really an inner join).
+ */
+ if (!is_valid_inner &&
+ (match_sjinfo == NULL || unique_ified))
return false; /* invalid join path */
/* Otherwise, it's a valid join */
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index a7b7b73ad6f..afb4f974e7a 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2150,6 +2150,20 @@ select count(*) from tenk1 x where
1
(1 row)
+-- try that with GEQO too
+begin;
+set geqo = on;
+set geqo_threshold = 2;
+select count(*) from tenk1 x where
+ x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and
+ x.unique1 = 0 and
+ x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1);
+ count
+-------
+ 1
+(1 row)
+
+rollback;
--
-- Clean up
--
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 29992ced0c2..123d1f3015d 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -343,6 +343,16 @@ select count(*) from tenk1 x where
x.unique1 = 0 and
x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1);
+-- try that with GEQO too
+begin;
+set geqo = on;
+set geqo_threshold = 2;
+select count(*) from tenk1 x where
+ x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and
+ x.unique1 = 0 and
+ x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1);
+rollback;
+
--
-- Clean up