Skip to content

Commit 4107478

Browse files
committed
Improve plpgsql's RAISE command. It is now possible to attach DETAIL and
HINT fields to a user-thrown error message, and to specify the SQLSTATE error code to use. The syntax has also been tweaked so that the Oracle-compatible case "RAISE exception_name" works (though you won't get a very nice error message if you just write that much). Lastly, support the Oracle-compatible syntax "RAISE" with no parameters to re-throw the current error from within an EXCEPTION block. In passing, allow the syntax SQLSTATE 'nnnnn' within EXCEPTION lists, so that there is a way to trap errors with custom SQLSTATE codes. Pavel Stehule and Tom Lane
1 parent 72e2db8 commit 4107478

File tree

9 files changed

+859
-159
lines changed

9 files changed

+859
-159
lines changed

doc/src/sgml/plpgsql.sgml

Lines changed: 104 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.128 2008/05/03 00:11:36 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.129 2008/05/13 22:10:29 tgl Exp $ -->
22

33
<chapter id="plpgsql">
44
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -2133,7 +2133,12 @@ END;
21332133
condition name <literal>OTHERS</> matches every error type except
21342134
<literal>QUERY_CANCELED</>. (It is possible, but often unwise,
21352135
to trap <literal>QUERY_CANCELED</> by name.) Condition names are
2136-
not case-sensitive.
2136+
not case-sensitive. Also, an error condition can be specified
2137+
by <literal>SQLSTATE</> code; for example these are equivalent:
2138+
<programlisting>
2139+
WHEN division_by_zero THEN ...
2140+
WHEN SQLSTATE '22012' THEN ...
2141+
</programlisting>
21372142
</para>
21382143

21392144
<para>
@@ -2750,13 +2755,19 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
27502755
raise errors.
27512756

27522757
<synopsis>
2753-
RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">expression</replaceable> <optional>, ...</optional></optional>;
2758+
RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">expression</replaceable> <optional>, ...</optional></optional> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
2759+
RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <replaceable class="parameter">condition_name</> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
2760+
RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> SQLSTATE '<replaceable class="parameter">sqlstate</>' <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
2761+
RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional>;
2762+
RAISE ;
27542763
</synopsis>
27552764

2756-
Possible levels are <literal>DEBUG</literal>,
2765+
The <replaceable class="parameter">level</replaceable> option specifies
2766+
the error severity. Allowed levels are <literal>DEBUG</literal>,
27572767
<literal>LOG</literal>, <literal>INFO</literal>,
27582768
<literal>NOTICE</literal>, <literal>WARNING</literal>,
2759-
and <literal>EXCEPTION</literal>.
2769+
and <literal>EXCEPTION</literal>, with <literal>EXCEPTION</literal>
2770+
being the default.
27602771
<literal>EXCEPTION</literal> raises an error (which normally aborts the
27612772
current transaction); the other levels only generate messages of different
27622773
priority levels.
@@ -2769,19 +2780,17 @@ RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="pa
27692780
</para>
27702781

27712782
<para>
2783+
After <replaceable class="parameter">level</replaceable> if any,
2784+
you can write a <replaceable class="parameter">format</replaceable>
2785+
(which must be a simple string literal, not an expression). The
2786+
format string specifies the error message text to be reported.
2787+
The format string can be followed
2788+
by optional argument expressions to be inserted into the message.
27722789
Inside the format string, <literal>%</literal> is replaced by the
2773-
next optional argument's string representation. Write
2790+
string representation of the next optional argument's value. Write
27742791
<literal>%%</literal> to emit a literal <literal>%</literal>.
2775-
Arguments can be simple variables or expressions,
2776-
but the format must be a simple string literal.
27772792
</para>
27782793

2779-
<!--
2780-
This example should work, but does not:
2781-
RAISE NOTICE 'Id number ' || key || ' not found!';
2782-
Put it back when we allow non-string-literal formats.
2783-
-->
2784-
27852794
<para>
27862795
In this example, the value of <literal>v_job_id</> will replace the
27872796
<literal>%</literal> in the string:
@@ -2791,19 +2800,90 @@ RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
27912800
</para>
27922801

27932802
<para>
2794-
This example will abort the transaction with the given error message:
2803+
You can attach additional information to the error report by writing
2804+
<literal>USING</> followed by <replaceable
2805+
class="parameter">option</replaceable> = <replaceable
2806+
class="parameter">expression</replaceable> items. The allowed
2807+
<replaceable class="parameter">option</replaceable> keywords are
2808+
<literal>MESSAGE</>, <literal>DETAIL</>, <literal>HINT</>, and
2809+
<literal>ERRCODE</>, while each <replaceable
2810+
class="parameter">expression</replaceable> can be any string-valued
2811+
expression.
2812+
<literal>MESSAGE</> sets the error message text (this option can't
2813+
be used in the form of <command>RAISE</> that includes a format
2814+
string before <literal>USING</>).
2815+
<literal>DETAIL</> supplies an error detail message, while
2816+
<literal>HINT</> supplies a hint message.
2817+
<literal>ERRCODE</> specifies the error code (SQLSTATE) to report,
2818+
either by condition name as shown in <xref linkend="errcodes-appendix">,
2819+
or directly as a five-character SQLSTATE code.
2820+
</para>
2821+
2822+
<para>
2823+
This example will abort the transaction with the given error message
2824+
and hint:
2825+
<programlisting>
2826+
RAISE EXCEPTION 'Nonexistent ID --> %', user_id USING HINT = 'Please check your user id';
2827+
</programlisting>
2828+
</para>
2829+
2830+
<para>
2831+
These two examples show equivalent ways of setting the SQLSTATE:
2832+
<programlisting>
2833+
RAISE 'Duplicate user ID: %', user_id USING ERRCODE = 'unique_violation';
2834+
RAISE 'Duplicate user ID: %', user_id USING ERRCODE = '23505';
2835+
</programlisting>
2836+
</para>
2837+
2838+
<para>
2839+
There is a second <command>RAISE</> syntax in which the main argument
2840+
is the condition name or SQLSTATE to be reported, for example:
2841+
<programlisting>
2842+
RAISE division_by_zero;
2843+
RAISE SQLSTATE '22012';
2844+
</programlisting>
2845+
In this syntax, <literal>USING</> can be used to supply a custom
2846+
error message, detail, or hint. Another way to do the earlier
2847+
example is
27952848
<programlisting>
2796-
RAISE EXCEPTION 'Nonexistent ID --> %', user_id;
2849+
RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;
27972850
</programlisting>
27982851
</para>
27992852

2853+
<para>
2854+
Still another variant is to write <literal>RAISE USING</> or <literal>RAISE
2855+
<replaceable class="parameter">level</replaceable> USING</> and put
2856+
everything else into the <literal>USING</> list.
2857+
</para>
2858+
2859+
<para>
2860+
The last variant of <command>RAISE</> has no parameters at all.
2861+
This form can only be used inside a <literal>BEGIN</> block's
2862+
<literal>EXCEPTION</> clause;
2863+
it causes the error currently being handled to be re-thrown to the
2864+
next enclosing block.
2865+
</para>
2866+
2867+
<para>
2868+
If no condition name nor SQLSTATE is specified in a
2869+
<command>RAISE EXCEPTION</command> command, the default is to use
2870+
<literal>RAISE_EXCEPTION</> (<literal>P0001</>). If no message
2871+
text is specified, the default is to use the condition name or
2872+
SQLSTATE as message text.
2873+
</para>
2874+
2875+
<note>
28002876
<para>
2801-
<command>RAISE EXCEPTION</command> presently always generates
2802-
the same <varname>SQLSTATE</varname> code, <literal>P0001</>, no matter what message
2803-
it is invoked with. It is possible to trap this exception with
2804-
<literal>EXCEPTION ... WHEN RAISE_EXCEPTION THEN ...</> but there
2805-
is no way to tell one <command>RAISE</> from another.
2877+
When specifying an error code by SQLSTATE code, you are not
2878+
limited to the predefined error codes, but can select any
2879+
error code consisting of five digits and/or upper-case ASCII
2880+
letters, other than <literal>00000</>. It is recommended that
2881+
you avoid throwing error codes that end in three zeroes, because
2882+
these are category codes and can only be trapped by trapping
2883+
the whole category.
28062884
</para>
2885+
</note>
2886+
28072887
</sect1>
28082888

28092889
<sect1 id="plpgsql-trigger">
@@ -4307,7 +4387,9 @@ $$ LANGUAGE plpgsql;
43074387
<callout arearefs="co.plpgsql-porting-raise">
43084388
<para>
43094389
The syntax of <literal>RAISE</> is considerably different from
4310-
Oracle's similar statement.
4390+
Oracle's statement, although the basic case <literal>RAISE</>
4391+
<replaceable class="parameter">exception_name</replaceable> works
4392+
similarly.
43114393
</para>
43124394
</callout>
43134395
<callout arearefs="co.plpgsql-porting-exception">

0 commit comments

Comments
 (0)