No Postgres, obtemos o "rastreamento de pilha" das exceções usando este código:
EXCEPTION WHEN others THEN
GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;
Isso funciona bem para exceções "naturais", mas se criarmos uma exceção usando
RAISE EXCEPTION 'This is an error!';
... então não há rastreamento de pilha. De acordo com uma entrada na lista de discussão , isso pode ser intencional, embora eu não consiga descobrir o porquê. Isso me faz querer descobrir outra maneira de lançar uma exceção diferente de usar RAISE
. Só estou perdendo algo óbvio? Alguém tem um truque para isso? Existe uma exceção que eu possa lançar o Postgres que contenha uma sequência de minha escolha, para que eu receba não apenas minha sequência na mensagem de erro, mas também o rastreamento completo da pilha?
Aqui está um exemplo completo:
CREATE OR REPLACE FUNCTION error_test() RETURNS json AS $$
DECLARE
v_error_stack text;
BEGIN
-- Comment this out to see how a "normal" exception will give you the stack trace
RAISE EXCEPTION 'This exception will not get a stack trace';
-- This will give a divide by zero error, complete with stack trace
SELECT 1/0;
-- In case of any exception, wrap it in error object and send it back as json
EXCEPTION WHEN others THEN
-- If the exception we're catching is one that Postgres threw,
-- like a divide by zero error, then this will get the full
-- stack trace of the place where the exception was thrown.
-- However, since we are catching an exception we raised manually
-- using RAISE EXCEPTION, there is no context/stack trace!
GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;
RAISE WARNING 'The stack trace of the error is: "%"', v_error_stack;
return to_json(v_error_stack);
END;
$$ LANGUAGE plpgsql;
error_info
? Parece um tipo personalizado.Respostas:
Esse comportamento parece ser por design.
No
src/pl/plpgsql/src/pl_exec.c
contexto de erro, o retorno de chamada verifica explicitamente se está sendo chamado no contexto de umaRAISE
instrução PL / PgSQL e, nesse caso, ignora a emissão do contexto de erro:Não consigo encontrar nenhuma referência específica sobre por que esse é o caso.
Internamente no servidor, a pilha de contexto é gerada processando o
error_context_stack
, que é um retorno de chamada em cadeia que acrescenta informações a uma lista quando chamada.Quando o PL / PgSQL entra em uma função, ele adiciona um item à pilha de retorno de chamada do contexto de erro. Quando sai de uma função, remove um item dessa pilha.
Se o relatório de erros do servidor PostgreSQL funcionar, como
ereport
ouelog
é chamado, ele chama o retorno de chamada do contexto de erro. Mas no PL / PgSQL, se perceber que está sendo chamado de umRAISE
retorno de chamada intencionalmente, não faz nada.Dado isso, não vejo como alcançar o que você deseja sem aplicar o patch no PostgreSQL. Sugiro postar mensagens para o pgsql-general perguntando por
RAISE
que não fornece o contexto de erro agora que o PL / PgSQL precisaGET STACKED DIAGNOSTICS
usá-lo.(BTW, o contexto de exceção não é um rastreamento de pilha como tal. Parece um pouco porque PL / PgSQL adiciona cada chamada de função à pilha, mas também é usado para outros detalhes no servidor.)
fonte
RAISE
é diminuída por essa verificação. Vou escrever para eles.Você pode contornar essa restrição e fazer com que o plpgsql emita o contexto de erro conforme desejado, chamando outra função que gera (aviso, aviso, ...) o erro para você.
Postei uma solução para isso há alguns anos - em um dos meus primeiros posts aqui no dba.SE :
Detalhes:
Expandi seu caso de teste publicado para demonstrar que funciona no Postgres 9.3:
SQL Fiddle.
fonte