postgres.git / summary / log / commit / refs
commit efeb12ef0bfef0b5aa966a56bb4dbb1f936bda0c
Author: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue Jun 20 14:29:57 2023 +0000
First released in: 16.0
Don't include outer join relids in lateral_relids bitmapsets.
This avoids an assertion failure when outer joins are rearranged
per identity 3. Listing only the baserels from a PlaceHolderVar's
ph_lateral set should be enough to ensure that the required values
are available when we need to compute the PHV --- it's what we
did before inventing nullingrel sets, after all. It's a bit
unsatisfying; but with beta2 hard upon us, there's not time to
look for an aesthetically cleaner fix.
Richard Guo and Tom Lane
Discussion: https://postgr.es/m/CAMbWs48Jcw-NvnxT23WiHP324wG44DvzcH1j4hc0Zn+3sR9cfg@mail.gmail.com
src/backend/optimizer/plan/initsplan.c | 16 +++++++++++++---
src/test/regress/expected/join.out | 17 +++++++++++++++++
src/test/regress/sql/join.sql | 7 +++++++
3 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 69ef483d283..b31d8921211 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -580,6 +580,7 @@ create_lateral_join_info(PlannerInfo *root)
{
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
Relids eval_at = phinfo->ph_eval_at;
+ Relids lateral_refs;
int varno;
if (phinfo->ph_lateral == NULL)
@@ -587,6 +588,15 @@ create_lateral_join_info(PlannerInfo *root)
found_laterals = true;
+ /*
+ * Include only baserels not outer joins in the evaluation sites'
+ * lateral relids. This avoids problems when outer join order gets
+ * rearranged, and it should still ensure that the lateral values are
+ * available when needed.
+ */
+ lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
+ Assert(!bms_is_empty(lateral_refs));
+
if (bms_get_singleton_member(eval_at, &varno))
{
/* Evaluation site is a baserel */
@@ -594,10 +604,10 @@ create_lateral_join_info(PlannerInfo *root)
brel->direct_lateral_relids =
bms_add_members(brel->direct_lateral_relids,
- phinfo->ph_lateral);
+ lateral_refs);
brel->lateral_relids =
bms_add_members(brel->lateral_relids,
- phinfo->ph_lateral);
+ lateral_refs);
}
else
{
@@ -610,7 +620,7 @@ create_lateral_join_info(PlannerInfo *root)
if (brel == NULL)
continue; /* ignore outer joins in eval_at */
brel->lateral_relids = bms_add_members(brel->lateral_relids,
- phinfo->ph_lateral);
+ lateral_refs);
}
}
}
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 35476a0d126..cd1163d039b 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2624,6 +2624,23 @@ select * from int8_tbl t1
-> Function Scan on generate_series
(7 rows)
+explain (costs off)
+select * from int8_tbl t1
+ left join int8_tbl t2 on true
+ left join lateral
+ (select t2.q1 from int8_tbl t3) s
+ on t2.q1 = 1;
+ QUERY PLAN
+-------------------------------------------
+ Nested Loop Left Join
+ -> Seq Scan on int8_tbl t1
+ -> Materialize
+ -> Nested Loop Left Join
+ Join Filter: (t2.q1 = 1)
+ -> Seq Scan on int8_tbl t2
+ -> Seq Scan on int8_tbl t3
+(7 rows)
+
explain (costs off)
select * from onek t1
left join onek t2 on true
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index d8d9579092d..7ca737eec0f 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -528,6 +528,13 @@ select * from int8_tbl t1
(select * from generate_series(t2.q1, 100)) s
on t2.q1 = 1;
+explain (costs off)
+select * from int8_tbl t1
+ left join int8_tbl t2 on true
+ left join lateral
+ (select t2.q1 from int8_tbl t3) s
+ on t2.q1 = 1;
+
explain (costs off)
select * from onek t1
left join onek t2 on true
[parent: 0655c03ef9cc]