Fix assertion failure with PL/Python exceptions
authorMichael Paquier <[email protected]>
Mon, 18 Sep 2023 23:31:06 +0000 (08:31 +0900)
committerMichael Paquier <[email protected]>
Mon, 18 Sep 2023 23:31:06 +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_5.out
src/pl/plpython/plpy_elog.c
src/pl/plpython/sql/plpython_error.sql

index 9af7ea7292df46aa2da3b1f212b81470e2a4bd81..68722b00097ed094db4e09ef11b44bba68cbab5d 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 plpython3u;
+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 7fe864a1a576dd11161c28cee92ae7d1eb5fa5db..fd9cd73be743afbd7953d18d45065dc1a9b40d78 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 plpython3u;
+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 7c627eacfbf716ddb985b46a17b396ad6fe0ce3c..70de5ba13d74b28ceb159b6f203433d352ad5139 100644 (file)
@@ -103,9 +103,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 11f14ec5a7cc65260d1aec0b7b71e844dfb4e283..9bb1c0b085aeb7a4c9895c2b0272dfe45a803e6c 100644 (file)
@@ -344,3 +344,14 @@ $$ LANGUAGE plpython3u;
 \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 plpython3u;
+
+SELECT python_error_detail();