1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-29 13:56:47 +03:00

Fix computation of varnullingrels when const-folding field selection.

We can simplify FieldSelect on a whole-row Var into a plain Var
for the selected field.  However, we should copy the whole-row Var's
varnullingrels when we do so, because the new Var is clearly nullable
by exactly the same rels as the original.  Failure to do this led to
errors like "wrong varnullingrels (b) (expected (b 3)) for Var 2/2".

Richard Guo, per bug #18184 from Marian Krucina.  Back-patch to
v16 where varnullingrels was introduced.

Discussion: https://postgr.es/m/18184-5868dd258782058e@postgresql.org
This commit is contained in:
Tom Lane 2023-11-09 15:46:16 -05:00
parent b630d9d6c8
commit 36f5594c0f
3 changed files with 51 additions and 6 deletions

View File

@ -3296,12 +3296,19 @@ eval_const_expressions_mutator(Node *node,
fselect->resulttype,
fselect->resulttypmod,
fselect->resultcollid))
return (Node *) makeVar(((Var *) arg)->varno,
{
Var *newvar;
newvar = makeVar(((Var *) arg)->varno,
fselect->fieldnum,
fselect->resulttype,
fselect->resulttypmod,
fselect->resultcollid,
((Var *) arg)->varlevelsup);
/* New Var is nullable by same rels as the old one */
newvar->varnullingrels = ((Var *) arg)->varnullingrels;
return (Node *) newvar;
}
}
if (arg && IsA(arg, RowExpr))
{

View File

@ -4133,6 +4133,32 @@ select * from mki4(42);
drop function mki8(bigint, bigint);
drop function mki4(int);
-- test const-folding of a whole-row Var into a per-field Var
-- (need to inline a function to reach this case, else parser does it)
create function f_field_select(t onek) returns int4 as
$$ select t.unique2; $$ language sql immutable;
explain (verbose, costs off)
select (t2.*).unique1, f_field_select(t2) from tenk1 t1
left join onek t2 on t1.unique1 = t2.unique1
left join int8_tbl t3 on true;
QUERY PLAN
--------------------------------------------------------------------
Nested Loop Left Join
Output: t2.unique1, t2.unique2
-> Hash Left Join
Output: t2.unique1, t2.unique2
Hash Cond: (t1.unique1 = t2.unique1)
-> Index Only Scan using tenk1_unique1 on public.tenk1 t1
Output: t1.unique1
-> Hash
Output: t2.unique1, t2.unique2
-> Seq Scan on public.onek t2
Output: t2.unique1, t2.unique2
-> Materialize
-> Seq Scan on public.int8_tbl t3
(13 rows)
drop function f_field_select(t onek);
--
-- test extraction of restriction OR clauses from join OR clause
-- (we used to only do this for indexable clauses)

View File

@ -1381,6 +1381,18 @@ select * from mki4(42);
drop function mki8(bigint, bigint);
drop function mki4(int);
-- test const-folding of a whole-row Var into a per-field Var
-- (need to inline a function to reach this case, else parser does it)
create function f_field_select(t onek) returns int4 as
$$ select t.unique2; $$ language sql immutable;
explain (verbose, costs off)
select (t2.*).unique1, f_field_select(t2) from tenk1 t1
left join onek t2 on t1.unique1 = t2.unique1
left join int8_tbl t3 on true;
drop function f_field_select(t onek);
--
-- test extraction of restriction OR clauses from join OR clause
-- (we used to only do this for indexable clauses)