Fix the way SJE removes references from PHVs

Add missing replacement of relids in phv->phexpr.  Also, remove extra
replace_relid() over phv->phrels.

Reported-by:  Zuming Jiang
Bug: #18187
Discussion: https://postgr.es/m/flat/18187-831da249cbd2ff8e%40postgresql.org
Author: Richard Guo
Reviewed-by: Andrei Lepikhov
This commit is contained in:
Alexander Korotkov 2023-11-09 14:06:11 +02:00
parent 3850d4dec1
commit b44a1708ab
3 changed files with 29 additions and 2 deletions

View File

@ -474,9 +474,9 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
/* ph_needed might or might not become empty */
phv->phrels = replace_relid(phv->phrels, relid, subst);
phv->phrels = replace_relid(phv->phrels, ojrelid, subst);
phinfo->ph_lateral = replace_relid(phinfo->ph_lateral, relid, subst);
phinfo->ph_var->phrels = replace_relid(phinfo->ph_var->phrels, relid, 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 */
}
}

View File

@ -6776,6 +6776,25 @@ SELECT c3.code FROM emp1 c3;
-> Seq Scan on emp1 c3
(7 rows)
-- Check that SJE removes references from PHVs correctly
explain (costs off)
select * from emp1 t1 left join
(select coalesce(t3.code, 1) from emp1 t2
left join (emp1 t3 join emp1 t4 on t3.id = t4.id)
on true)
on true;
QUERY PLAN
----------------------------------------------------
Nested Loop Left Join
-> Seq Scan on emp1 t1
-> Materialize
-> Nested Loop Left Join
-> Seq Scan on emp1 t2
-> Materialize
-> Seq Scan on emp1 t4
Filter: (id IS NOT NULL)
(8 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

@ -2580,6 +2580,14 @@ WHERE c2.id IS NOT NULL
EXCEPT ALL
SELECT c3.code FROM emp1 c3;
-- Check that SJE removes references from PHVs correctly
explain (costs off)
select * from emp1 t1 left join
(select coalesce(t3.code, 1) from emp1 t2
left join (emp1 t3 join emp1 t4 on t3.id = t4.id)
on true)
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.