From f8f776c0338e7b923bed9fe80e2b3e5bb9326026 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Fri, 3 May 2024 01:51:13 +0300 Subject: [PATCH v2 4/4] Fix self-join elimination work with PlaceHolderInfo.ph_lateral After removing the relation participating in the later, relation may end up depending on itself according to the PlaceHolderInfo.ph_lateral. This commit makes remove_rel_from_query() revise PlaceHolderInfo.ph_lateral after replacing relids there. Discussion: https://postgr.es/m/CAMbWs49Q8g1LPVCeNHYv-Y-gFo826ertrg6nYNC9LL%3D8%3DzHP3g%40mail.gmail.com Author: Richard Guo Reviewed-by: Alexander Korotkov --- src/backend/optimizer/plan/analyzejoins.c | 7 +++++++ src/test/regress/expected/join.out | 13 +++++++++++++ src/test/regress/sql/join.sql | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index d82d86b37f4..b52cce05da8 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -462,7 +462,14 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel, phinfo->ph_needed = replace_relid(phinfo->ph_needed, ojrelid, subst); /* ph_needed might or might not become empty */ + /* + * ph_lateral might contain rels mentioned in ph_eval_at after the + * replacement. We will remove them. But first check they aren't + * overlapping already. + */ + Assert(!bms_overlap(phinfo->ph_lateral, phinfo->ph_eval_at)); phinfo->ph_lateral = replace_relid(phinfo->ph_lateral, relid, subst); + phinfo->ph_lateral = bms_difference(phinfo->ph_lateral, phinfo->ph_eval_at); /* ph_lateral might or might not be empty */ phv->phrels = replace_relid(phv->phrels, relid, subst); diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 02765a7bc93..1b0b11c048d 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -6234,6 +6234,19 @@ select * from sj t1 Filter: (t1.a = a) (8 rows) +-- Ensure that SJE does not form a self-referential lateral dependency +explain (costs off) +select * from sj t1 + left join lateral + (select t1.a as t1a, * from sj t2) s + on true +where t1.a = s.a; + QUERY PLAN +--------------------------- + Seq Scan on sj t2 + Filter: (a IS NOT NULL) +(2 rows) + -- Degenerated case. explain (costs off) select * from diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 0a4ea3df19c..a9844892067 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -2360,6 +2360,14 @@ select * from sj t1 (select * from sj tablesample system(t1.b)) s on t1.a = s.a; +-- Ensure that SJE does not form a self-referential lateral dependency +explain (costs off) +select * from sj t1 + left join lateral + (select t1.a as t1a, * from sj t2) s + on true +where t1.a = s.a; + -- Degenerated case. explain (costs off) select * from -- 2.39.3 (Apple Git-145)