In Postgres erhalten wir die "Stapelverfolgung" von Ausnahmen unter Verwendung dieses Codes:
EXCEPTION WHEN others THEN
GET STACKED DIAGNOSTICS v_error_stack = PG_EXCEPTION_CONTEXT;
Dies funktioniert gut für "natürliche" Ausnahmen, aber wenn wir eine Ausnahme mit auslösen
RAISE EXCEPTION 'This is an error!';
... dann gibt es keine Stack-Trace. Laut einem Eintrag in einer Mailingliste könnte dies beabsichtigt sein, obwohl ich für mein ganzes Leben nicht herausfinden kann, warum. Ich möchte einen anderen Weg finden, um eine andere Ausnahme als die Verwendung auszulösenRAISE
. Vermisse ich nur etwas Offensichtliches? Hat jemand einen Trick dafür? Gibt es eine Ausnahme, die Postgres auslösen kann und die eine Zeichenfolge meiner Wahl enthält, sodass ich nicht nur meine Zeichenfolge in der Fehlermeldung, sondern auch die vollständige Stapelverfolgung erhalte?
Hier ist ein vollständiges Beispiel:
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
? Sieht aus wie ein benutzerdefinierter Typ.Antworten:
Dieses Verhalten scheint beabsichtigt zu sein.
Im
src/pl/plpgsql/src/pl_exec.c
Fehlerkontext prüft der Rückruf explizit, ob er im Kontext einer PL / PgSQL-RAISE
Anweisung aufgerufen wird , und überspringt in diesem Fall das Ausgeben des Fehlerkontexts:Ich kann keinen konkreten Hinweis darauf finden, warum dies der Fall ist.
Intern auf dem Server wird der Kontextstapel durch Verarbeiten des generiert.
error_context_stack
Hierbei handelt es sich um einen verketteten Rückruf, der beim Aufruf Informationen an eine Liste anfügt.Wenn PL / PgSQL eine Funktion eingibt, fügt es dem Fehlerkontext-Rückrufstapel ein Element hinzu. Wenn eine Funktion verlassen wird, wird ein Element von diesem Stapel entfernt.
Wenn die Fehlerberichterstattungsfunktionen des PostgreSQL-Servers wie
ereport
oderelog
aufgerufen werden, wird der Fehlerkontext-Rückruf aufgerufen. Aber in PL / PgSQL, wenn es bemerkt, dass es von einemRAISE
seiner Rückrufe aufgerufen wird, tun sie absichtlich nichts.Angesichts dessen sehe ich keine Möglichkeit, das zu erreichen, was Sie wollen, ohne PostgreSQL zu patchen. Ich schlage vor, E-Mails an pgsql-general zu senden und zu fragen, warum
RAISE
der Fehlerkontext nicht bereitgestellt wirdGET STACKED DIAGNOSTICS
, da PL / PgSQL ihn verwenden muss.(Übrigens ist der Ausnahmekontext kein Stack-Trace als solcher. Er sieht ein bisschen wie einer aus, da PL / PgSQL jeden Funktionsaufruf zum Stack hinzufügt, aber auch für andere Details auf dem Server verwendet wird.)
quelle
RAISE
wird durch diese Prüfung verringert. Ich werde ihnen schreiben.Sie können diese Einschränkung umgehen und plpgsql dazu bringen, den gewünschten Fehlerkontext auszugeben, indem Sie eine andere Funktion aufrufen, die den Fehler für Sie auslöst (Warnung, Hinweis, ...).
Ich habe vor ein paar Jahren eine Lösung dafür veröffentlicht - in einem meiner ersten Beiträge hier auf dba.SE :
Einzelheiten:
Ich habe Ihren veröffentlichten Testfall erweitert, um zu demonstrieren, dass er in Postgres 9.3 funktioniert:
SQL Fiddle.
quelle