diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 9e6f57f4c9e5339b8a7ac4543591797a4fca9365..350fde29c21f78cf73d5e89412b6f58bd843c064 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 a7b7b73ad6f13095653a9b2104690b0d808b2406..afb4f974e7a252074bdfa4b1d8de733debb2a1f4 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 29992ced0c230bf7d7b81bac0f22919b14096791..123d1f3015daba2cd402194f7d8f822d82c28c20 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