Você está confundindo níveis de abstração. Como outras respostas já apontam,
CREATE TYPE
apenas registra um tipo (composto/linha) no sistema. Enquanto um ROW
construtor realmente retorna uma linha. Um tipo de linha criado com o
ROW
construtor não preserva os nomes das colunas, o que fica evidente quando você tenta converter a linha em JSON. Enquanto isso,
ROW
é apenas uma palavra de ruído a maior parte do tempo. A documentação:
Demonstração:
SELECT t AS r1, row_to_json(t) AS j1
, ROW(1, 'x', NUMERIC '42.1') AS r2, row_to_json(ROW(1, 'x', NUMERIC '42.1')) AS j2
, (1, 'x', NUMERIC '42.1') AS r3, row_to_json( (1, 'x', NUMERIC '42.1')) AS j3
, (1, 'x', '42.1')::myrowtype AS r4, row_to_json((1, 'x', '42.1')::myrowtype) AS j4
FROM (SELECT 1, 'x', NUMERIC '42.1') t;
db<>fiddle aqui
sqlfiddle
r1
e j1
preserve os nomes das colunas originais.r2
e j2
não.r3
e j3
são os mesmos; para demonstrar como ROW
é apenas ruído.r4
e j4
carregam os nomes das colunas do tipo registrado. Você pode converter a linha (registro) em um tipo de linha registrado se número e tipos de dados dos elementos correspondem ao tipo de linha - nomes dos campos de entrada são ignorados.