diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 26441fc2d964b7dfca134485728cd64825532b6d..4a41e5746bb478b1712fccbf480cb82dcccc545c 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -694,9 +694,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 @@ -713,6 +713,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 b484620dba11ba0183708236f9a61c4e176e4477..97a6a6101530ea51540fa2e018ab8a6122e3dfd3 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2277,6 +2277,48 @@ WHERE d.f1 IS NULL; 9999 (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 -- diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 39a701a9e02d013dff85c4a3b947bbb13a681556..fb6981f54d3c4cf9ee459e4c3bd47e82c0b75531 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -443,6 +443,23 @@ LEFT JOIN ( ) AS d ON (a.f1 = d.f1) 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 --