diff options
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 7 | ||||
-rw-r--r-- | src/test/regress/expected/join.out | 42 | ||||
-rw-r--r-- | src/test/regress/sql/join.sql | 17 |
3 files changed, 63 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index a779bc3fa0e..5328f19afea 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -680,9 +680,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 @@ -699,6 +699,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 bfb9e841ad9..548b074c145 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2278,6 +2278,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 5a9f1df5506..794fbfe0ad7 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -444,6 +444,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 -- |