aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/initsplan.c7
-rw-r--r--src/test/regress/expected/join.out42
-rw-r--r--src/test/regress/sql/join.sql17
3 files changed, 63 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index a7655e4a710..00b2625d342 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -1165,9 +1165,9 @@ make_outerjoininfo(PlannerInfo *root,
* For a lower OJ in our RHS, if our join condition does not use the
* lower join's RHS and the lower OJ's join condition is strict, we
* can interchange the ordering of the two OJs; otherwise we must add
- * lower OJ's full syntactic relset to min_righthand. Here, we must
- * preserve ordering anyway if either the current join is a semijoin,
- * or the lower OJ is either a semijoin or an antijoin.
+ * the lower OJ's full syntactic relset to min_righthand. Also, we
+ * must preserve ordering anyway if either the current join or the
+ * lower OJ is either a semijoin or an antijoin.
*
* Here, we have to consider that "our join condition" includes any
* clauses that syntactically appeared above the lower OJ and below
@@ -1184,6 +1184,7 @@ make_outerjoininfo(PlannerInfo *root,
{
if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
jointype == JOIN_SEMI ||
+ jointype == JOIN_ANTI ||
otherinfo->jointype == JOIN_SEMI ||
otherinfo->jointype == JOIN_ANTI ||
!otherinfo->lhs_strict || otherinfo->delay_upper_joins)
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index e4f3f22e0b9..ed9ad0e135d 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2284,6 +2284,48 @@ WHERE d.f1 IS NULL;
(3 rows)
--
+-- regression test for proper handling of outer joins within antijoins
+--
+create temp table tt4x(c1 int, c2 int, c3 int);
+explain (costs off)
+select * from tt4x t1
+where not exists (
+ select 1 from tt4x t2
+ left join tt4x t3 on t2.c3 = t3.c1
+ left join ( select t5.c1 as c1
+ from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1
+ ) a1 on t3.c2 = a1.c1
+ where t1.c1 = t2.c2
+);
+ QUERY PLAN
+---------------------------------------------------------
+ Hash Anti Join
+ Hash Cond: (t1.c1 = t2.c2)
+ -> Seq Scan on tt4x t1
+ -> Hash
+ -> Merge Right Join
+ Merge Cond: (t5.c1 = t3.c2)
+ -> Merge Join
+ Merge Cond: (t4.c2 = t5.c1)
+ -> Sort
+ Sort Key: t4.c2
+ -> Seq Scan on tt4x t4
+ -> Sort
+ Sort Key: t5.c1
+ -> Seq Scan on tt4x t5
+ -> Sort
+ Sort Key: t3.c2
+ -> Merge Left Join
+ Merge Cond: (t2.c3 = t3.c1)
+ -> Sort
+ Sort Key: t2.c3
+ -> Seq Scan on tt4x t2
+ -> Sort
+ Sort Key: t3.c1
+ -> Seq Scan on tt4x t3
+(24 rows)
+
+--
-- regression test for problems of the sort depicted in bug #3494
--
create temp table tt5(f1 int, f2 int);
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index d0cf0a041d6..5b65ea8c922 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -448,6 +448,23 @@ LEFT JOIN (
WHERE d.f1 IS NULL;
--
+-- regression test for proper handling of outer joins within antijoins
+--
+
+create temp table tt4x(c1 int, c2 int, c3 int);
+
+explain (costs off)
+select * from tt4x t1
+where not exists (
+ select 1 from tt4x t2
+ left join tt4x t3 on t2.c3 = t3.c1
+ left join ( select t5.c1 as c1
+ from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1
+ ) a1 on t3.c2 = a1.c1
+ where t1.c1 = t2.c2
+);
+
+--
-- regression test for problems of the sort depicted in bug #3494
--