-- the trigger handler once. the errors and subsequent core dump were
-- interesting.
SELECT invalid_type_uncaught('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_uncaught"
-DETAIL: plpy.SPIError: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: plpy.SPIError: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_uncaught"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_uncaught"
SELECT invalid_type_caught('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_caught"
-DETAIL: plpy.SPIError: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: plpy.SPIError: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_caught"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_caught"
SELECT invalid_type_reraised('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_reraised"
-DETAIL: plpy.SPIError: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: plpy.SPIError: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_reraised"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_reraised"
SELECT valid_type('rick');
valid_type
------------
-- Test Unicode error handling.
--
SELECT unicode_return_error();
-ERROR: PL/Python: could not create string representation of Python object in PL/Python function "unicode_return_error" while creating return value
+ERROR: PL/Python: could not create string representation of Python object, while creating return value
DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_return_error"
INSERT INTO unicode_test (testvalue) VALUES ('test');
-ERROR: PL/Python: could not compute string representation of Python object in PL/Python function "unicode_trigger_error" while modifying trigger row
+ERROR: PL/Python: could not compute string representation of Python object, while modifying trigger row
DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_trigger_error"
SELECT unicode_plan_error1();
-WARNING: PL/Python: in PL/Python function "unicode_plan_error1"
-DETAIL: plpy.Error: unrecognized error in PLy_spi_execute_plan
-ERROR: PL/Python: PL/Python function "unicode_plan_error1" could not execute plan
+WARNING: PL/Python: plpy.Error: unrecognized error in PLy_spi_execute_plan
+CONTEXT: PL/Python function "unicode_plan_error1"
+ERROR: PL/Python: could not execute plan
DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_plan_error1"
SELECT unicode_plan_error2();
-ERROR: PL/Python: PL/Python function "unicode_plan_error2" could not execute plan
+ERROR: PL/Python: could not execute plan
DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_plan_error2"
-- the trigger handler once. the errors and subsequent core dump were
-- interesting.
SELECT invalid_type_uncaught('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_uncaught"
-DETAIL: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_uncaught"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_uncaught"
SELECT invalid_type_caught('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_caught"
-DETAIL: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_caught"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_caught"
SELECT invalid_type_reraised('rick');
-WARNING: PL/Python: in PL/Python function "invalid_type_reraised"
-DETAIL: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+WARNING: PL/Python: <class 'plpy.SPIError'>: unrecognized error in PLy_spi_prepare
+CONTEXT: PL/Python function "invalid_type_reraised"
ERROR: type "test" does not exist
+CONTEXT: PL/Python function "invalid_type_reraised"
SELECT valid_type('rick');
valid_type
------------
-- Test Unicode error handling.
--
SELECT unicode_return_error();
-ERROR: PL/Python: could not create string representation of Python object in PL/Python function "unicode_return_error" while creating return value
+ERROR: PL/Python: could not create string representation of Python object, while creating return value
DETAIL: <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_return_error"
INSERT INTO unicode_test (testvalue) VALUES ('test');
-ERROR: PL/Python: could not compute string representation of Python object in PL/Python function "unicode_trigger_error" while modifying trigger row
+ERROR: PL/Python: could not compute string representation of Python object, while modifying trigger row
DETAIL: <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_trigger_error"
SELECT unicode_plan_error1();
-WARNING: PL/Python: in PL/Python function "unicode_plan_error1"
-DETAIL: <class 'plpy.Error'>: unrecognized error in PLy_spi_execute_plan
-ERROR: PL/Python: PL/Python function "unicode_plan_error1" could not execute plan
+WARNING: PL/Python: <class 'plpy.Error'>: unrecognized error in PLy_spi_execute_plan
+CONTEXT: PL/Python function "unicode_plan_error1"
+ERROR: PL/Python: could not execute plan
DETAIL: <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_plan_error1"
SELECT unicode_plan_error2();
-ERROR: PL/Python: PL/Python function "unicode_plan_error2" could not execute plan
+ERROR: PL/Python: could not execute plan
DETAIL: <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
+CONTEXT: PL/Python function "unicode_plan_error2"
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
insert into trigger_test values(1,'insert');
NOTICE: ("TD[args] => ['23', 'skidoo']",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => INSERT',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'insert'}",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[old] => None',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
+CONTEXT: PL/Python function "trigger_data"
update trigger_test set v = 'update' where i = 1;
NOTICE: ("TD[args] => ['23', 'skidoo']",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => UPDATE',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[new] => {'i': 1, 'v': 'update'}",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[old] => {'i': 1, 'v': 'insert'}",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
+CONTEXT: PL/Python function "trigger_data"
delete from trigger_test;
NOTICE: ("TD[args] => ['23', 'skidoo']",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[event] => DELETE',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[level] => ROW',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[name] => show_trigger_data_trig',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[new] => None',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ("TD[old] => {'i': 1, 'v': 'update'}",)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[relid] => bogus:12345',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_name] => trigger_test',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[table_schema] => public',)
+CONTEXT: PL/Python function "trigger_data"
NOTICE: ('TD[when] => BEFORE',)
+CONTEXT: PL/Python function "trigger_data"
DROP TRIGGER show_trigger_data_trig on trigger_test;
--
SELECT import_fail();
NOTICE: ('import socket failed -- No module named foosocket',)
+CONTEXT: PL/Python function "import_fail"
import_fail
--------------------
failed as expected
SELECT test_void_func2(); -- should fail
ERROR: PL/Python function with return type "void" did not return None
+CONTEXT: PL/Python function "test_void_func2"
SELECT test_return_none(), test_return_none() IS NULL AS "is null";
test_return_none | is null
------------------+---------
/**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL
*
- * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.122 2009/06/11 14:49:14 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.123 2009/07/20 08:01:06 petere Exp $
*
*********************************************************************
*/
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))
}
PG_END_TRY();
+ /* Pop the error context stack */
+ error_context_stack = plerrcontext.previous;
+
PLy_curr_procedure = save_curr_proc;
Py_DECREF(proc->me);
{
plstr = PyObject_Str(plval);
if (!plstr)
- PLy_elog(ERROR, "could not compute string representation of Python object in PL/Python function \"%s\" while modifying trigger row",
- proc->proname);
+ PLy_elog(ERROR, "could not compute string representation of Python object, while modifying trigger row");
src = PyString_AsString(plstr);
modvalues[i] =
fcinfo->isnull = false;
plrv_so = PyObject_Str(plrv);
if (!plrv_so)
- PLy_elog(ERROR, "could not create string representation of Python object in PL/Python function \"%s\" while creating return value", proc->proname);
+ PLy_elog(ERROR, "could not create string representation of Python object, while creating return value");
plrv_sc = PyString_AsString(plrv_so);
rv = InputFunctionCall(&proc->result.out.d.typfunc,
plrv_sc,
}
if (PyList_SetItem(args, i, arg) == -1)
- PLy_elog(ERROR, "PyList_SetItem() failed for PL/Python function \"%s\" while setting up arguments", proc->proname);
+ PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
if (proc->argnames && proc->argnames[i] &&
PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
- PLy_elog(ERROR, "PyDict_SetItemString() failed for PL/Python function \"%s\" while setting up arguments", proc->proname);
+ PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
arg = NULL;
}
}
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();
PyObject *so = PyObject_Str(list);
if (!so)
- PLy_elog(ERROR, "PL/Python function \"%s\" could not execute plan",
- PLy_procedure_name(PLy_curr_procedure));
+ PLy_elog(ERROR, "could not execute plan");
sv = PyString_AsString(so);
PLy_exception_set_plural(PLy_exc_spi_error,
"Expected sequence of %d argument, got %d: %s",
{
so = PyObject_Str(elem);
if (!so)
- PLy_elog(ERROR, "PL/Python function \"%s\" could not execute plan",
- PLy_procedure_name(PLy_curr_procedure));
+ PLy_elog(ERROR, "could not execute plan");
Py_DECREF(elem);
PG_TRY();
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();
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();
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 by 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,...)
xmsg = PLy_traceback(&xlevel);
- initStringInfo(&emsg);
- for (;;)
+ if (fmt)
{
- va_list ap;
- bool success;
-
- va_start(ap, fmt);
- success = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap);
- va_end(ap);
- if (success)
- break;
- enlargeStringInfo(&emsg, emsg.maxlen);
+ initStringInfo(&emsg);
+ for(;;)
+ {
+ va_list ap;
+ bool success;
+
+ va_start(ap, fmt);
+ success = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap);
+ va_end(ap);
+ if (success)
+ break;
+ enlargeStringInfo(&emsg, emsg.maxlen);
+ }
}
PG_TRY();
{
- ereport(elevel,
- (errmsg("PL/Python: %s", emsg.data),
- (xmsg) ? errdetail("%s", xmsg) : 0));
+ 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();
{
- pfree(emsg.data);
+ if (fmt)
+ pfree(emsg.data);
if (xmsg)
pfree(xmsg);
PG_RE_THROW();
}
PG_END_TRY();
- pfree(emsg.data);
+ if (fmt)
+ pfree(emsg.data);
if (xmsg)
pfree(xmsg);
}