@@ -962,7 +962,7 @@ $$ LANGUAGE plpythonu;
962962 Functions accessing the database might encounter errors, which
963963 will cause them to abort and raise an exception. Both
964964 <function>plpy.execute</function> and
965- <function>plpy.prepare</function> can raise an instance of
965+ <function>plpy.prepare</function> can raise an instance of a subclass of
966966 <literal>plpy.SPIError</literal>, which by default will terminate
967967 the function. This error can be handled just like any other
968968 Python exception, by using the <literal>try/except</literal>
@@ -978,6 +978,53 @@ CREATE FUNCTION try_adding_joe() RETURNS text AS $$
978978$$ LANGUAGE plpythonu;
979979</programlisting>
980980 </para>
981+
982+ <para>
983+ The actual class of the exception being raised corresponds to the
984+ specific condition that caused the error. Refer
985+ to <xref linkend="errcodes-table"> for a list of possible
986+ conditions. The module
987+ <literal>plpy.spiexceptions</literal> defines an exception class
988+ for each <productname>PostgreSQL</productname> condition, deriving
989+ their names from the condition name. For
990+ instance, <literal>division_by_zero</literal>
991+ becomes <literal>DivisionByZero</literal>, <literal>unique_violation</literal>
992+ becomes <literal>UniqueViolation</literal>, <literal>fdw_error</literal>
993+ becomes <literal>FdwError</literal>, and so on. Each of these
994+ exception classes inherits from <literal>SPIError</literal>. This
995+ separation makes it easier to handle specific errors, for
996+ instance:
997+ <programlisting>
998+ CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$
999+ from plpy import spiexceptions
1000+ try:
1001+ plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"])
1002+ plpy.execute(plan, [numerator, denominator])
1003+ except spiexceptions.DivisionByZero:
1004+ return "denominator cannot equal zero"
1005+ except spiexceptions.UniqueViolation:
1006+ return "already have that fraction"
1007+ except plpy.SPIError, e:
1008+ return "other error, SQLSTATE %s" % e.sqlstate
1009+ else:
1010+ return "fraction inserted"
1011+ $$ LANGUAGE plpythonu;
1012+ </programlisting>
1013+ Note that because all exceptions from
1014+ the <literal>plpy.spiexceptions</literal> module inherit
1015+ from <literal>SPIError</literal>, an <literal>except</literal>
1016+ clause handling it will catch any database access error.
1017+ </para>
1018+
1019+ <para>
1020+ As an alternative way of handling different error conditions, you
1021+ can catch the <literal>SPIError</literal> exception and determine
1022+ the specific error condition inside the <literal>except</literal>
1023+ block by looking at the <literal>sqlstate</literal> attribute of
1024+ the exception object. This attribute is a string value containing
1025+ the <quote>SQLSTATE</quote> error code. This approach provides
1026+ approximately the same functionality
1027+ </para>
9811028 </sect2>
9821029 </sect1>
9831030
0 commit comments