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

Reply via email to