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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers