diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index da258968b8c..948c2bf06db 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -3296,12 +3296,19 @@ eval_const_expressions_mutator(Node *node, fselect->resulttype, fselect->resulttypmod, fselect->resultcollid)) - return (Node *) makeVar(((Var *) arg)->varno, - fselect->fieldnum, - fselect->resulttype, - fselect->resulttypmod, - fselect->resultcollid, - ((Var *) arg)->varlevelsup); + { + 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)) { diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index ddc4e692329..b60f5a67c1e 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -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) diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index a41787d1f1e..fbaee480d32 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -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)