From 1218780ccebace6a4c4d5872d7b158aa36e6882e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 10 Jun 2022 10:35:57 -0400 Subject: [PATCH] Un-break whole-row Vars referencing domain-over-composite types. In commit ec62cb0aa, I foolishly replaced ExecEvalWholeRowVar's lookup_rowtype_tupdesc_domain call with just lookup_rowtype_tupdesc, because I didn't see how a domain could be involved there, and there were no regression test cases to jog my memory. But the existing code was correct, so revert that change and add a test case showing why it's necessary. (Note: per comment in struct DatumTupleFields, it is correct to produce an output tuple that's labeled with the base composite type, not the domain; hence just blindly looking through the domain is correct here.) Per bug #17515 from Dan Kubb. Back-patch to v11 where domains over composites became a thing. Discussion: https://postgr.es/m/17515-a24737438363aca0@postgresql.org --- src/backend/executor/execExprInterp.c | 6 +++++- src/test/regress/expected/domain.out | 23 +++++++++++++++++++++++ src/test/regress/sql/domain.sql | 9 +++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index e44ad68cda..eaec697bb3 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -4138,8 +4138,12 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) * generates an INT4 NULL regardless of the dropped column type). * If we find a dropped column and cannot verify that case (1) * holds, we have to use the slow path to check (2) for each row. + * + * If vartype is a domain over composite, just look through that + * to the base composite type. */ - var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1); + var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype, + -1, false); slot_tupdesc = slot->tts_tupleDescriptor; diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 8faf46d404..73b010f6ed 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -277,6 +277,29 @@ Rules: ON DELETE TO dcomptable DO INSTEAD UPDATE dcomptable SET d1.r = (dcomptable.d1).r - 1::double precision, d1.i = (dcomptable.d1).i + 1::double precision WHERE (dcomptable.d1).i > 0::double precision +create function makedcomp(r float8, i float8) returns dcomptype +as 'select row(r, i)' language sql; +select makedcomp(1,2); + makedcomp +----------- + (1,2) +(1 row) + +select makedcomp(2,1); -- fail +ERROR: value for domain dcomptype violates check constraint "c1" +select * from makedcomp(1,2) m; + r | i +---+--- + 1 | 2 +(1 row) + +select m, m is not null from makedcomp(1,2) m; + m | ?column? +-------+---------- + (1,2) | t +(1 row) + +drop function makedcomp(float8, float8); drop table dcomptable; drop type comptype cascade; NOTICE: drop cascades to type dcomptype diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index bf48c53e9c..f2ca1fb675 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -154,6 +154,15 @@ create rule silly as on delete to dcomptable do instead update dcomptable set d1.r = (d1).r - 1, d1.i = (d1).i + 1 where (d1).i > 0; \d+ dcomptable +create function makedcomp(r float8, i float8) returns dcomptype +as 'select row(r, i)' language sql; + +select makedcomp(1,2); +select makedcomp(2,1); -- fail +select * from makedcomp(1,2) m; +select m, m is not null from makedcomp(1,2) m; + +drop function makedcomp(float8, float8); drop table dcomptable; drop type comptype cascade;