aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-05-23 16:34:38 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-05-23 16:34:38 +0000
commit7df4cf7fd3aff6a3ebc4a223bb98c768e9bbe821 (patch)
treeffc548c52ae1dba40a54bb13e68e31b72482167b
parentc8518845de62e64eec3d863d4e149da72cacdd9f (diff)
downloadpostgresql-7df4cf7fd3aff6a3ebc4a223bb98c768e9bbe821.tar.gz
postgresql-7df4cf7fd3aff6a3ebc4a223bb98c768e9bbe821.zip
Fix oversight in join removal patch: we have to delete the removed relation
from SpecialJoinInfo relid sets as well. Per example from Vaclav Novotny.
-rw-r--r--src/backend/optimizer/plan/analyzejoins.c20
-rw-r--r--src/test/regress/expected/join.out14
-rw-r--r--src/test/regress/sql/join.sql6
3 files changed, 39 insertions, 1 deletions
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index da6482b4c3c..a06e647f4b8 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/analyzejoins.c,v 1.1 2010/03/28 22:59:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/analyzejoins.c,v 1.2 2010/05/23 16:34:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -344,6 +344,24 @@ remove_rel_from_query(PlannerInfo *root, int relid)
}
/*
+ * Likewise remove references from SpecialJoinInfo data structures.
+ *
+ * This is relevant in case the outer join we're deleting is nested
+ * inside other outer joins: the upper joins' relid sets have to be
+ * adjusted. The RHS of the target outer join will be made empty here,
+ * but that's OK since caller will delete that SpecialJoinInfo entirely.
+ */
+ foreach(l, root->join_info_list)
+ {
+ SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
+
+ sjinfo->min_lefthand = bms_del_member(sjinfo->min_lefthand, relid);
+ sjinfo->min_righthand = bms_del_member(sjinfo->min_righthand, relid);
+ sjinfo->syn_lefthand = bms_del_member(sjinfo->syn_lefthand, relid);
+ sjinfo->syn_righthand = bms_del_member(sjinfo->syn_righthand, relid);
+ }
+
+ /*
* Likewise remove references from PlaceHolderVar data structures.
*
* Here we have a special case: if a PHV's eval_at set is just the target
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 5fd7d79b45d..6dfc710be01 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2525,6 +2525,20 @@ explain (costs off)
Seq Scan on a
(1 row)
+-- check optimization of outer join within another special join
+explain (costs off)
+select id from a where id in (
+ select b.id from b left join c on b.id = c.id
+);
+ QUERY PLAN
+----------------------------
+ Hash Semi Join
+ Hash Cond: (a.id = b.id)
+ -> Seq Scan on a
+ -> Hash
+ -> Seq Scan on b
+(5 rows)
+
rollback;
create temp table parent (k int primary key, pd int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "parent_pkey" for table "parent"
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index d627973a091..8657636757a 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -588,6 +588,12 @@ explain (costs off)
SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id)
ON (a.b_id = b.id);
+-- check optimization of outer join within another special join
+explain (costs off)
+select id from a where id in (
+ select b.id from b left join c on b.id = c.id
+);
+
rollback;
create temp table parent (k int primary key, pd int);