Fix assertion failure with PL/Python exceptions
authorMichael Paquier <[email protected]>
Mon, 18 Sep 2023 23:31:31 +0000 (08:31 +0900)
committerMichael Paquier <[email protected]>
Mon, 18 Sep 2023 23:31:31 +0000 (08:31 +0900)
PLy_elog() was not able to handle correctly cases where a SPI called
failed, which would fill in a DETAIL string able to trigger an
assertion.  We may want to improve this infrastructure so as it is able
to provide any extra detail information provided by an error stack, but
this is left as a future improvement as it could impact existing error
stacks and any applications that depend on them.  For now, the assertion
is removed and a regression test is added to cover the case of a failure
with a detail string.

This problem exists since 2bd78eb8d51c, so backpatch all the way down
with tweaks to the regression tests output added where required.

Author: Alexander Lakhin
Discussion: https://postgr.es/m/18070-ab9c171cbf4ebb0f@postgresql.org
Backpatch-through: 11

src/pl/plpython/expected/plpython_error.out
src/pl/plpython/expected/plpython_error_0.out
src/pl/plpython/expected/plpython_error_5.out
src/pl/plpython/plpy_elog.c
src/pl/plpython/sql/plpython_error.sql

index 4d615b41cc50960394cef51890b032044f3defef..94874668bad8ac27b607107a5257663eb2c4168e 100644 (file)
@@ -445,3 +445,16 @@ PL/Python function "notice_outerfunc"
                 1
 (1 row)
 
+/* test error logged with an underlying exception that includes a detail
+ * string (bug #18070).
+ */
+CREATE FUNCTION python_error_detail() RETURNS SETOF text AS $$
+  plan = plpy.prepare("SELECT to_date('xy', 'DD') d")
+  for row in plpy.cursor(plan):
+    yield row['d']
+$$ LANGUAGE plpythonu;
+SELECT python_error_detail();
+ERROR:  error fetching next item from iterator
+DETAIL:  spiexceptions.InvalidDatetimeFormat: invalid value "xy" for "DD"
+CONTEXT:  Traceback (most recent call last):
+PL/Python function "python_error_detail"
index 290902b1828546f504ebad1072ca1bd4c0faf44b..66684d94d86a2b224aae78b4c71a904e93696fdc 100644 (file)
@@ -445,3 +445,16 @@ PL/Python function "notice_outerfunc"
                 1
 (1 row)
 
+/* test error logged with an underlying exception that includes a detail
+ * string (bug #18070).
+ */
+CREATE FUNCTION python_error_detail() RETURNS SETOF text AS $$
+  plan = plpy.prepare("SELECT to_date('xy', 'DD') d")
+  for row in plpy.cursor(plan):
+    yield row['d']
+$$ LANGUAGE plpythonu;
+SELECT python_error_detail();
+ERROR:  error fetching next item from iterator
+DETAIL:  spiexceptions.InvalidDatetimeFormat: invalid value "xy" for "DD"
+CONTEXT:  Traceback (most recent call last):
+PL/Python function "python_error_detail"
index bc66ab553400fced4d9fa835bb6e531c6671bae9..0e67b5a57510fcfb3823b480ff31533519104c58 100644 (file)
@@ -445,3 +445,16 @@ PL/Python function "notice_outerfunc"
                 1
 (1 row)
 
+/* test error logged with an underlying exception that includes a detail
+ * string (bug #18070).
+ */
+CREATE FUNCTION python_error_detail() RETURNS SETOF text AS $$
+  plan = plpy.prepare("SELECT to_date('xy', 'DD') d")
+  for row in plpy.cursor(plan):
+    yield row['d']
+$$ LANGUAGE plpythonu;
+SELECT python_error_detail();
+ERROR:  error fetching next item from iterator
+DETAIL:  spiexceptions.InvalidDatetimeFormat: invalid value "xy" for "DD"
+CONTEXT:  Traceback (most recent call last):
+PL/Python function "python_error_detail"
index df5caaba487b3c6ddb8e3b599e7bc7f132b7eccc..c052a24c52e0da7f48600904c1c1ce89707ba7f8 100644 (file)
@@ -105,9 +105,6 @@ PLy_elog_impl(int elevel, const char *fmt,...)
        }
        primary = emsg.data;
 
-       /* Since we have a format string, we cannot have a SPI detail. */
-       Assert(detail == NULL);
-
        /* If there's an exception message, it goes in the detail. */
        if (xmsg)
            detail = xmsg;
index d712eb1078f849d55fdadcdc1c4a4b76d5fd2d65..3f835051e75281d49b3dfdbfadfefca51695e5e1 100644 (file)
@@ -344,3 +344,14 @@ $$ LANGUAGE plpythonu;
 \set SHOW_CONTEXT always
 
 SELECT notice_outerfunc();
+
+/* test error logged with an underlying exception that includes a detail
+ * string (bug #18070).
+ */
+CREATE FUNCTION python_error_detail() RETURNS SETOF text AS $$
+  plan = plpy.prepare("SELECT to_date('xy', 'DD') d")
+  for row in plpy.cursor(plan):
+    yield row['d']
+$$ LANGUAGE plpythonu;
+
+SELECT python_error_detail();