Fix how SJE checks against PHVs

It seems that a PHV evaluated/needed at or below the self join should not have
a problem if we remove the self join.  But this requires further investigation.
For now, we just do not remove self joins if the rel to be removed is laterally
referenced by PHVs.

Discussion: https://postgr.es/m/CAMbWs4-ns73VF9gi37q61G3dS6Xuos+HtryMaBh37WQn=BsaJw@mail.gmail.com
Author: Richard Guo
This commit is contained in:
Alexander Korotkov 2023-11-10 22:46:46 +02:00
parent eb81e8e790
commit b7f315c9d7
3 changed files with 23 additions and 2 deletions

View File

@ -476,7 +476,6 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
phv->phrels = replace_relid(phv->phrels, ojrelid, subst);
Assert(!bms_is_empty(phv->phrels));
replace_varno((Node *) phv->phexpr, relid, subst);
phinfo->ph_lateral = replace_relid(phinfo->ph_lateral, relid, subst);
Assert(phv->phnullingrels == NULL); /* no need to adjust */
}
}
@ -2134,7 +2133,8 @@ remove_self_joins_one_group(PlannerInfo *root, Relids relids)
/* there isn't any other place to eval PHV */
if (bms_is_subset(phinfo->ph_eval_at, joinrelids) ||
bms_is_subset(phinfo->ph_needed, joinrelids))
bms_is_subset(phinfo->ph_needed, joinrelids) ||
bms_is_member(r, phinfo->ph_lateral))
break;
}
if (lc)

View File

@ -6821,6 +6821,21 @@ on true;
Filter: (id IS NOT NULL)
(8 rows)
-- Check that SJE does not remove self joins if a PHV references the removed
-- rel laterally.
explain (costs off)
select * from emp1 t1 join emp1 t2 on t1.id = t2.id left join
lateral (select t1.id as t1id, * from generate_series(1,1) t3) s on true;
QUERY PLAN
---------------------------------------------------
Nested Loop Left Join
-> Nested Loop
-> Seq Scan on emp1 t1
-> Index Scan using emp1_pkey on emp1 t2
Index Cond: (id = t1.id)
-> Function Scan on generate_series t3
(6 rows)
-- We can remove the join even if we find the join can't duplicate rows and
-- the base quals of each side are different. In the following case we end up
-- moving quals over to s1 to make it so it can't match any rows.

View File

@ -2600,6 +2600,12 @@ select * from emp1 t1 left join
on true)
on true;
-- Check that SJE does not remove self joins if a PHV references the removed
-- rel laterally.
explain (costs off)
select * from emp1 t1 join emp1 t2 on t1.id = t2.id left join
lateral (select t1.id as t1id, * from generate_series(1,1) t3) s on true;
-- We can remove the join even if we find the join can't duplicate rows and
-- the base quals of each side are different. In the following case we end up
-- moving quals over to s1 to make it so it can't match any rows.