@@ -962,7 +962,7 @@ $$ LANGUAGE plpythonu;
962
962
Functions accessing the database might encounter errors, which
963
963
will cause them to abort and raise an exception. Both
964
964
<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
966
966
<literal>plpy.SPIError</literal>, which by default will terminate
967
967
the function. This error can be handled just like any other
968
968
Python exception, by using the <literal>try/except</literal>
@@ -978,6 +978,53 @@ CREATE FUNCTION try_adding_joe() RETURNS text AS $$
978
978
$$ LANGUAGE plpythonu;
979
979
</programlisting>
980
980
</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>
981
1028
</sect2>
982
1029
</sect1>
983
1030
0 commit comments