Eu uso Postgresql 9.1, com Ubuntu 12.04.
Inspirado pela resposta de Craig à minha pergunta Concatenação do tipo setof ou setof record , pensei em usar return query
, setof record
, e um gerador de série nesta função plpgsql:
create or replace function compute_all_pair_by_craig(id_obj bigint)
returns setof record as $$
begin
return query select o.id, generate_series(0,o.value) from m_obj as o;
end;
$$ language plpgsql;
Durante a execução, recebo o erro:
ERROR: set_valued function called in context that cannot accept a set
O que está errado ? Ao contrário de Craig, digo à função para retornar setof record
.
Posso conseguir algo que funcione exatamente como Craig, ou seja, definindo um tipo create type pair_id_value as (idx bigint, value integer)
e fazendo com que minha função plpgsql retorne um setof of pair_id_value
em vez de um setof record
.
Mas mesmo com esta solução funcional, ainda não entendo porque select id, generate_series(0,13)
sozinho retornará um resultado em duas colunas ... e ao contrário, chamar a função (retorna setof pair_id_value) com return query select id, generate_series(0,my_obj.value) from my_obj
retornará um resultado em apenas uma coluna cujo campo se parece this "(123123,0)" "(123123,1)" "(123123,2)" (3 linhas) que obviamente são tuplas.
É um caso em que uma tabela temporária deve/deve ser criada?
A mensagem de erro não é muito útil:
mas se você reformular a consulta para chamá-la como uma função de retorno de conjunto adequada, verá o problema real:
Se você estiver usando
SETOF RECORD
sem umaOUT
lista de parâmetros, deverá especificar os resultados na instrução de chamada, por exemplo:No entanto, é muito melhor usar
RETURNS TABLE
ouOUT
parâmetros. Com a sintaxe anterior, sua função seria:Isso pode ser chamado no contexto da lista SELECT e pode ser usado sem criar um tipo explicitamente ou especificar a estrutura do resultado no local da chamada.
Quanto à segunda metade da questão, o que está acontecendo é que o primeiro caso especifica duas colunas separadas em uma lista SELECT, enquanto o segundo retorna um único composto. Na verdade, não tem a ver com como você está retornando o resultado, mas como você está invocando a função. Se criarmos a função de exemplo:
Você verá a diferença nas duas maneiras de chamar uma função de retorno de conjunto - na
SELECT
lista, uma extensão não padrão específica do PostgreSQL com comportamento peculiar:ou como uma tabela da maneira mais padrão: