I wrote:
> I think that the real issue here doesn't have anything to do
> with NEW/OLD as such, but is related to the representational difference
> between record and row variables.
BTW, just to reinforce that it's not NEW/OLD that's the issue, here's
a simplified version of Oleg's non-trigger example:
CREATE TYPE composite_type AS (
c1 bigint,
c2 bigint
);
CREATE TABLE buggy (
id bigint,
bug composite_type
);
CREATE OR REPLACE FUNCTION test_bug () RETURNS void AS
$body$
DECLARE
tmp_row buggy;
tmp_rec record;
BEGIN
tmp_rec := ROW(1, NULL)::buggy;
tmp_row := tmp_rec;
IF tmp_row::text <> tmp_rec::text THEN
RAISE EXCEPTION '% <> %', tmp_row, tmp_rec;
END IF;
END;
$body$
LANGUAGE plpgsql;
select test_bug();
The issue here isn't even with the declared variables themselves,
it's with the sub-record or sub-row for the composite-type column "bug".
In the value assigned to tmp_rec that's an atomic NULL, but there's no
such representation available when that's copied to tmp_row's sub-row,
so you get ROW(NULL,NULL) instead.
regards, tom lane