blob: 6e0825473484a55eabcdf7a08be593597cadfbfe [file]
--
-- Multi-consumer CTE column pruning (ORCA).
--
-- A CTE referenced by several consumers has its shared-scan output pruned to the
-- union of all consumers' required columns. Because ShareInputScan does not
-- project, every consumer must expose exactly the producer's surviving columns.
-- A consumer that projects a superset (e.g. SELECT *) and is referenced directly
-- with a join key used to keep an identity column map and read the shared tuple
-- by stale positions, producing wrong results (join key read from the wrong slot
-- -> LEFT JOIN yields NULLs) and "invalid attnum N for relation shareX_refY" in
-- EXPLAIN. See CPhysicalCTEConsumer. These queries assert correct results under
-- both optimizers.
--
create schema cte_mc;
set search_path = cte_mc;
create table policy(pr_id text, pied_id text, p_id text, amnt numeric(18,2),
guarantee_period text, main_risk text, premium numeric(18,2));
create table mid(p_id text, tenant_id text, act_premium numeric(18,2));
insert into policy values('pr1','k1','p1',300000,'1','Y',290);
insert into mid values('p1','t1',290);
analyze policy;
analyze mid;
-- The "info" consumer projects SELECT * but only p_id/amnt/main_risk are needed
-- outside; the producer prunes pr_id/pied_id/guarantee_period. i.amnt and i.p_id
-- must not come back NULL. EXPLAIN previously raised "invalid attnum".
explain (costs off)
with agent as (select pr_id,pied_id,p_id,amnt,guarantee_period,main_risk,premium from policy),
det as (select p_id, sum(premium) premium from agent group by p_id),
info as (select * from agent where main_risk='Y' and p_id='p1'),
unused as (select 1 from mid)
select i.amnt, m.tenant_id, m.p_id, i.p_id, d.p_id, d.premium, m.act_premium
from mid m
left join det d on d.p_id=m.p_id and d.premium=m.act_premium
left join info i on m.p_id=i.p_id
where m.p_id='p1'
order by 1,2,3,4;
with agent as (select pr_id,pied_id,p_id,amnt,guarantee_period,main_risk,premium from policy),
det as (select p_id, sum(premium) premium from agent group by p_id),
info as (select * from agent where main_risk='Y' and p_id='p1'),
unused as (select 1 from mid)
select i.amnt, m.tenant_id, m.p_id, i.p_id, d.p_id, d.premium, m.act_premium
from mid m
left join det d on d.p_id=m.p_id and d.premium=m.act_premium
left join info i on m.p_id=i.p_id
where m.p_id='p1'
order by 1,2,3,4;
-- Variant: project a different surviving column (main_risk) from the SELECT *
-- consumer to exercise a different pruned layout.
explain (costs off)
with agent as (select pr_id,pied_id,p_id,amnt,guarantee_period,main_risk,premium from policy),
det as (select p_id, sum(premium) premium from agent group by p_id),
info as (select * from agent where p_id='p1')
select m.p_id, i.main_risk, i.amnt, d.premium
from mid m
left join det d on d.p_id=m.p_id
left join info i on m.p_id=i.p_id
where m.p_id='p1'
order by 1,2,3;
with agent as (select pr_id,pied_id,p_id,amnt,guarantee_period,main_risk,premium from policy),
det as (select p_id, sum(premium) premium from agent group by p_id),
info as (select * from agent where p_id='p1')
select m.p_id, i.main_risk, i.amnt, d.premium
from mid m
left join det d on d.p_id=m.p_id
left join info i on m.p_id=i.p_id
where m.p_id='p1'
order by 1,2,3;
-- Three consumers, each needing a different subset (join key on each).
explain (costs off)
with agent as (select p_id, amnt, main_risk, premium from policy)
select x.p_id, y.amnt, z.main_risk
from agent x
join agent y on x.p_id=y.p_id
join agent z on x.p_id=z.p_id
order by 1,2,3;
with agent as (select p_id, amnt, main_risk, premium from policy)
select x.p_id, y.amnt, z.main_risk
from agent x
join agent y on x.p_id=y.p_id
join agent z on x.p_id=z.p_id
order by 1,2,3;
-- start_ignore
drop schema cte_mc cascade;
-- end_ignore