diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e5b3cb5fcc3..a80d4e1681e 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -1432,6 +1432,13 @@ make_outerjoininfo(PlannerInfo *root, */ strict_relids = find_nonnullable_rels((Node *) clause); + /* + * find_nonnullable_rels looks inside PlaceHolderVars, so it can report + * rels that the clause references only laterally. Ignore those, since + * like clause_relids we treat a PHV as computed at its ph_eval_at. + */ + strict_relids = bms_int_members(strict_relids, clause_relids); + /* Remember whether the clause is strict for any LHS relations */ sjinfo->lhs_strict = bms_overlap(strict_relids, left_rels); diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index b8829c97616..19d92a82607 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -5797,6 +5797,36 @@ where s2.q2 > t1.f1; (1 row) reset from_collapse_limit; +-- +-- check that an outer join is not taken to commute with a lower outer join +-- when its clause references the lower join's RHS only laterally within a +-- PlaceHolderVar +-- +explain (costs off) +select 1 from int4_tbl t1 + left join int4_tbl t2 on true + left join lateral (select t2.f1, 1 from int4_tbl t3) s(x, y) on true + left join int4_tbl t4 on t4.f1 = s.x + join int4_tbl t5 on true +where s.y is not null; + QUERY PLAN +------------------------------------------------------- + Nested Loop + -> Hash Left Join + Hash Cond: ((t2.f1) = t4.f1) + -> Nested Loop + -> Nested Loop Left Join + -> Seq Scan on int4_tbl t1 + -> Materialize + -> Seq Scan on int4_tbl t2 + -> Seq Scan on int4_tbl t3 + Filter: (1 IS NOT NULL) + -> Hash + -> Seq Scan on int4_tbl t4 + -> Materialize + -> Seq Scan on int4_tbl t5 +(14 rows) + -- -- test successful handling of full join underneath left join (bug #14105) -- diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index f8fc1ddd742..d536f17d897 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -2044,6 +2044,20 @@ where s2.q2 > t1.f1; reset from_collapse_limit; +-- +-- check that an outer join is not taken to commute with a lower outer join +-- when its clause references the lower join's RHS only laterally within a +-- PlaceHolderVar +-- + +explain (costs off) +select 1 from int4_tbl t1 + left join int4_tbl t2 on true + left join lateral (select t2.f1, 1 from int4_tbl t3) s(x, y) on true + left join int4_tbl t4 on t4.f1 = s.x + join int4_tbl t5 on true +where s.y is not null; + -- -- test successful handling of full join underneath left join (bug #14105) --