During the review of the patch about improved PL/Python data type support, I
figured this could be somewhat simplified if PL/Python used the errcontext()
mechanisms instead of passing the function name around everywhere in order to
use it in error messages.
I have produced the attached patch. The errcontext stuff is a bit obscure to
me though, so perhaps someone could look it over.
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 50b48ac..b8e2816 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -332,18 +332,33 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
fmgr_info_cxt(functionId, finfo, TopMemoryContext);
}
+static void
+plpython_error_callback(void *arg)
+{
+ if (PLy_curr_procedure)
+ errcontext("PL/Python function \"%s\"", PLy_procedure_name(PLy_curr_procedure));
+}
+
Datum
plpython_call_handler(PG_FUNCTION_ARGS)
{
Datum retval;
PLyProcedure *save_curr_proc;
PLyProcedure *volatile proc = NULL;
+ ErrorContextCallback plerrcontext;
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "SPI_connect failed");
save_curr_proc = PLy_curr_procedure;
+ /*
+ * Setup error traceback support for ereport()
+ */
+ plerrcontext.callback = plpython_error_callback;
+ plerrcontext.previous = error_context_stack;
+ error_context_stack = &plerrcontext;
+
PG_TRY();
{
if (CALLED_AS_TRIGGER(fcinfo))
@@ -377,6 +392,9 @@ plpython_call_handler(PG_FUNCTION_ARGS)
}
PG_END_TRY();
+ /* Pop the error context stack */
+ error_context_stack = plerrcontext.previous;
+
PLy_curr_procedure = save_curr_proc;
Py_DECREF(proc->me);
@@ -2460,9 +2478,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
if (!PyErr_Occurred())
PLy_exception_set(PLy_exc_spi_error,
"unrecognized error in PLy_spi_prepare");
- /* XXX this oughta be replaced with errcontext mechanism */
- PLy_elog(WARNING, "in PL/Python function \"%s\"",
- PLy_procedure_name(PLy_curr_procedure));
+ PLy_elog(WARNING, NULL);
return NULL;
}
PG_END_TRY();
@@ -2624,9 +2640,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
if (!PyErr_Occurred())
PLy_exception_set(PLy_exc_error,
"unrecognized error in PLy_spi_execute_plan");
- /* XXX this oughta be replaced with errcontext mechanism */
- PLy_elog(WARNING, "in PL/Python function \"%s\"",
- PLy_procedure_name(PLy_curr_procedure));
+ PLy_elog(WARNING, NULL);
return NULL;
}
PG_END_TRY();
@@ -2671,9 +2685,7 @@ PLy_spi_execute_query(char *query, long limit)
if (!PyErr_Occurred())
PLy_exception_set(PLy_exc_spi_error,
"unrecognized error in PLy_spi_execute_query");
- /* XXX this oughta be replaced with errcontext mechanism */
- PLy_elog(WARNING, "in PL/Python function \"%s\"",
- PLy_procedure_name(PLy_curr_procedure));
+ PLy_elog(WARNING, NULL);
return NULL;
}
PG_END_TRY();
@@ -2987,9 +2999,11 @@ PLy_exception_set_plural(PyObject *exc,
PyErr_SetString(exc, buf);
}
-/* Emit a PG error or notice, together with any available info about the
- * current Python error. This should be used to propagate Python errors
- * into PG.
+/* Emit a PG error or notice, together with any available info about
+ * the current Python error, previously set with PLy_exception_set().
+ * This should be used to propagate Python errors into PG. If fmt is
+ * NULL, the Python error becomes the primary error message, otherwise
+ * it becomes the detail.
*/
static void
PLy_elog(int elevel, const char *fmt,...)
@@ -3000,6 +3014,8 @@ PLy_elog(int elevel, const char *fmt,...)
xmsg = PLy_traceback(&xlevel);
+ if (fmt)
+ {
initStringInfo(&emsg);
for (;;)
{
@@ -3013,15 +3029,21 @@ PLy_elog(int elevel, const char *fmt,...)
break;
enlargeStringInfo(&emsg, emsg.maxlen);
}
+ }
PG_TRY();
{
+ if (fmt)
ereport(elevel,
(errmsg("PL/Python: %s", emsg.data),
(xmsg) ? errdetail("%s", xmsg) : 0));
+ else
+ ereport(elevel,
+ (errmsg("PL/Python: %s", xmsg)));
}
PG_CATCH();
{
+ if (fmt)
pfree(emsg.data);
if (xmsg)
pfree(xmsg);
@@ -3029,6 +3051,7 @@ PLy_elog(int elevel, const char *fmt,...)
}
PG_END_TRY();
+ if (fmt)
pfree(emsg.data);
if (xmsg)
pfree(xmsg);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers