aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/restrictinfo.c13
-rw-r--r--src/test/regress/expected/join.out68
-rw-r--r--src/test/regress/sql/join.sql20
3 files changed, 100 insertions, 1 deletions
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index d2bc096e1cc..760d24bebf3 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -544,13 +544,24 @@ clause_is_computable_at(PlannerInfo *root,
RestrictInfo *rinfo,
Relids eval_relids)
{
- Relids clause_relids = rinfo->clause_relids;
+ Relids clause_relids;
ListCell *lc;
/* Nothing to do if no outer joins have been performed yet. */
if (!bms_overlap(eval_relids, root->outer_join_rels))
return true;
+ /*
+ * For an ordinary qual clause, we consider the actual clause_relids as
+ * explained above. However, it's possible for multiple members of a
+ * group of clone quals to have the same clause_relids, so for clones use
+ * the required_relids instead to ensure we select just one of them.
+ */
+ if (rinfo->has_clone || rinfo->is_clone)
+ clause_relids = rinfo->required_relids;
+ else
+ clause_relids = rinfo->clause_relids;
+
foreach(lc, root->join_info_list)
{
SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 8fa2b376f3a..1fd75c8f582 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2500,6 +2500,74 @@ select * from int4_tbl t1
-> Seq Scan on int4_tbl t4
(12 rows)
+explain (costs off)
+select * from int4_tbl t1
+ left join (int4_tbl t2 left join int4_tbl t3 on t2.f1 > 0) on t2.f1 > 1
+ left join int4_tbl t4 on t2.f1 > 2 and t3.f1 > 3
+where t1.f1 = coalesce(t2.f1, 1);
+ QUERY PLAN
+----------------------------------------------------
+ Nested Loop Left Join
+ Join Filter: ((t2.f1 > 2) AND (t3.f1 > 3))
+ -> Nested Loop Left Join
+ Join Filter: (t2.f1 > 0)
+ -> Nested Loop Left Join
+ Filter: (t1.f1 = COALESCE(t2.f1, 1))
+ -> Seq Scan on int4_tbl t1
+ -> Materialize
+ -> Seq Scan on int4_tbl t2
+ Filter: (f1 > 1)
+ -> Seq Scan on int4_tbl t3
+ -> Materialize
+ -> Seq Scan on int4_tbl t4
+(13 rows)
+
+explain (costs off)
+select * from int4_tbl t1
+ left join ((select t2.f1 from int4_tbl t2
+ left join int4_tbl t3 on t2.f1 > 0
+ where t3.f1 is null) s
+ left join tenk1 t4 on s.f1 > 1)
+ on s.f1 = t1.f1;
+ QUERY PLAN
+-------------------------------------------------
+ Nested Loop Left Join
+ Join Filter: (t2.f1 > 1)
+ -> Hash Right Join
+ Hash Cond: (t2.f1 = t1.f1)
+ -> Nested Loop Left Join
+ Join Filter: (t2.f1 > 0)
+ Filter: (t3.f1 IS NULL)
+ -> Seq Scan on int4_tbl t2
+ -> Materialize
+ -> Seq Scan on int4_tbl t3
+ -> Hash
+ -> Seq Scan on int4_tbl t1
+ -> Seq Scan on tenk1 t4
+(13 rows)
+
+explain (costs off)
+select * from onek t1
+ left join onek t2 on t1.unique1 = t2.unique1
+ left join onek t3 on t2.unique1 = t3.unique1
+ left join onek t4 on t3.unique1 = t4.unique1 and t2.unique2 = t4.unique2;
+ QUERY PLAN
+------------------------------------------------------------------------
+ Hash Left Join
+ Hash Cond: ((t3.unique1 = t4.unique1) AND (t2.unique2 = t4.unique2))
+ -> Hash Left Join
+ Hash Cond: (t2.unique1 = t3.unique1)
+ -> Hash Left Join
+ Hash Cond: (t1.unique1 = t2.unique1)
+ -> Seq Scan on onek t1
+ -> Hash
+ -> Seq Scan on onek t2
+ -> Hash
+ -> Seq Scan on onek t3
+ -> Hash
+ -> Seq Scan on onek t4
+(13 rows)
+
--
-- check a case where we formerly got confused by conflicting sort orders
-- in redundant merge join path keys
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 641fd1a21b9..84547c7dffa 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -488,6 +488,26 @@ select * from int4_tbl t1
left join int4_tbl t3 on t2.f1 = t3.f1
left join int4_tbl t4 on t3.f1 != t4.f1;
+explain (costs off)
+select * from int4_tbl t1
+ left join (int4_tbl t2 left join int4_tbl t3 on t2.f1 > 0) on t2.f1 > 1
+ left join int4_tbl t4 on t2.f1 > 2 and t3.f1 > 3
+where t1.f1 = coalesce(t2.f1, 1);
+
+explain (costs off)
+select * from int4_tbl t1
+ left join ((select t2.f1 from int4_tbl t2
+ left join int4_tbl t3 on t2.f1 > 0
+ where t3.f1 is null) s
+ left join tenk1 t4 on s.f1 > 1)
+ on s.f1 = t1.f1;
+
+explain (costs off)
+select * from onek t1
+ left join onek t2 on t1.unique1 = t2.unique1
+ left join onek t3 on t2.unique1 = t3.unique1
+ left join onek t4 on t3.unique1 = t4.unique1 and t2.unique2 = t4.unique2;
+
--
-- check a case where we formerly got confused by conflicting sort orders
-- in redundant merge join path keys