mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Postpone extParam/allParam calculations until the very end of planning.
Until now we computed these Param ID sets at the end of subquery_planner, but that approach depends on subquery_planner returning a concrete Plan tree. We would like to switch over to returning one or more Paths for a subquery, and in that representation the necessary details aren't fully fleshed out (not to mention that we don't really want to do this work for Paths that end up getting discarded). Hence, refactor so that we can compute the param ID sets at the end of planning, just before set_plan_references is run. The main change necessary to make this work is that we need to capture the set of outer-level Param IDs available to the current query level before exiting subquery_planner, since the outer levels' plan_params lists are transient. (That's not going to pose a problem for returning Paths, since all the work involved in producing that data is part of expression preprocessing, which will continue to happen before Paths are produced.) On the plus side, this change gets rid of several existing kluges. Eventually I'd like to get rid of SS_finalize_plan altogether in favor of doing this work during set_plan_references, but that will require some complex rejiggering because SS_finalize_plan needs to visit subplans and initplans before the main plan. So leave that idea for another day.
This commit is contained in:
@ -4889,6 +4889,63 @@ select * from
|
||||
0 | 9998 | 0
|
||||
(1 row)
|
||||
|
||||
-- check proper extParam/allParam handling (this isn't exactly a LATERAL issue,
|
||||
-- but we can make the test case much more compact with LATERAL)
|
||||
explain (verbose, costs off)
|
||||
select * from (values (0), (1)) v(id),
|
||||
lateral (select * from int8_tbl t1,
|
||||
lateral (select * from
|
||||
(select * from int8_tbl t2
|
||||
where q1 = any (select q2 from int8_tbl t3
|
||||
where q2 = (select greatest(t1.q1,t2.q2))
|
||||
and (select v.id=0)) offset 0) ss2) ss
|
||||
where t1.q1 = ss.q2) ss0;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------
|
||||
Nested Loop
|
||||
Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
|
||||
-> Seq Scan on public.int8_tbl t1
|
||||
Output: t1.q1, t1.q2
|
||||
-> Nested Loop
|
||||
Output: "*VALUES*".column1, ss2.q1, ss2.q2
|
||||
-> Values Scan on "*VALUES*"
|
||||
Output: "*VALUES*".column1
|
||||
-> Subquery Scan on ss2
|
||||
Output: ss2.q1, ss2.q2
|
||||
Filter: (t1.q1 = ss2.q2)
|
||||
-> Seq Scan on public.int8_tbl t2
|
||||
Output: t2.q1, t2.q2
|
||||
Filter: (SubPlan 3)
|
||||
SubPlan 3
|
||||
-> Result
|
||||
Output: t3.q2
|
||||
One-Time Filter: $4
|
||||
InitPlan 1 (returns $2)
|
||||
-> Result
|
||||
Output: GREATEST($0, t2.q2)
|
||||
InitPlan 2 (returns $4)
|
||||
-> Result
|
||||
Output: ($3 = 0)
|
||||
-> Seq Scan on public.int8_tbl t3
|
||||
Output: t3.q1, t3.q2
|
||||
Filter: (t3.q2 = $2)
|
||||
(27 rows)
|
||||
|
||||
select * from (values (0), (1)) v(id),
|
||||
lateral (select * from int8_tbl t1,
|
||||
lateral (select * from
|
||||
(select * from int8_tbl t2
|
||||
where q1 = any (select q2 from int8_tbl t3
|
||||
where q2 = (select greatest(t1.q1,t2.q2))
|
||||
and (select v.id=0)) offset 0) ss2) ss
|
||||
where t1.q1 = ss.q2) ss0;
|
||||
id | q1 | q2 | q1 | q2
|
||||
----+------------------+-------------------+------------------+------------------
|
||||
0 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789
|
||||
0 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
|
||||
0 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789
|
||||
(3 rows)
|
||||
|
||||
-- test some error cases where LATERAL should have been used but wasn't
|
||||
select f1,g from int4_tbl a, (select f1 as g) ss;
|
||||
ERROR: column "f1" does not exist
|
||||
|
@ -1542,6 +1542,27 @@ select * from
|
||||
where f1 = any (select unique1 from tenk1
|
||||
where unique2 = v.x offset 0)) ss;
|
||||
|
||||
-- check proper extParam/allParam handling (this isn't exactly a LATERAL issue,
|
||||
-- but we can make the test case much more compact with LATERAL)
|
||||
explain (verbose, costs off)
|
||||
select * from (values (0), (1)) v(id),
|
||||
lateral (select * from int8_tbl t1,
|
||||
lateral (select * from
|
||||
(select * from int8_tbl t2
|
||||
where q1 = any (select q2 from int8_tbl t3
|
||||
where q2 = (select greatest(t1.q1,t2.q2))
|
||||
and (select v.id=0)) offset 0) ss2) ss
|
||||
where t1.q1 = ss.q2) ss0;
|
||||
|
||||
select * from (values (0), (1)) v(id),
|
||||
lateral (select * from int8_tbl t1,
|
||||
lateral (select * from
|
||||
(select * from int8_tbl t2
|
||||
where q1 = any (select q2 from int8_tbl t3
|
||||
where q2 = (select greatest(t1.q1,t2.q2))
|
||||
and (select v.id=0)) offset 0) ss2) ss
|
||||
where t1.q1 = ss.q2) ss0;
|
||||
|
||||
-- test some error cases where LATERAL should have been used but wasn't
|
||||
select f1,g from int4_tbl a, (select f1 as g) ss;
|
||||
select f1,g from int4_tbl a, (select a.f1 as g) ss;
|
||||
|
Reference in New Issue
Block a user