diff --git a/src/pl/plpython/expected/plpython_record.out b/src/pl/plpython/expected/plpython_record.out index 9e4645d56cb49c3c771f4046bfd6e16ca0636419..c8c4f9d5a3cbb02a8d549dff1dd6f7216b8c7d6a 100644 --- a/src/pl/plpython/expected/plpython_record.out +++ b/src/pl/plpython/expected/plpython_record.out @@ -313,13 +313,15 @@ $$ LANGUAGE plpythonu; SELECT * FROM test_type_record_error1(); ERROR: key "second" not found in mapping HINT: To return null in a column, add the value None to the mapping with the key named after the column. -CONTEXT: PL/Python function "test_type_record_error1" +CONTEXT: while creating return value +PL/Python function "test_type_record_error1" CREATE FUNCTION test_type_record_error2() RETURNS type_record AS $$ return [ 'first' ] $$ LANGUAGE plpythonu; SELECT * FROM test_type_record_error2(); ERROR: length of returned sequence did not match number of columns in row -CONTEXT: PL/Python function "test_type_record_error2" +CONTEXT: while creating return value +PL/Python function "test_type_record_error2" CREATE FUNCTION test_type_record_error3() RETURNS type_record AS $$ class type_record: pass type_record.first = 'first' @@ -328,4 +330,5 @@ $$ LANGUAGE plpythonu; SELECT * FROM test_type_record_error3(); ERROR: attribute "second" does not exist in Python object HINT: To return null in a column, let the returned object have an attribute named after column with value None. -CONTEXT: PL/Python function "test_type_record_error3" +CONTEXT: while creating return value +PL/Python function "test_type_record_error3" diff --git a/src/pl/plpython/expected/plpython_trigger.out b/src/pl/plpython/expected/plpython_trigger.out index b60796dab5b07df6c8405bdfa2bb4e9cd92f9a1a..6be1c9dd0c1e6d904394abbb4d3e0c76cf9c6b63 100644 --- a/src/pl/plpython/expected/plpython_trigger.out +++ b/src/pl/plpython/expected/plpython_trigger.out @@ -353,7 +353,8 @@ BEFORE UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE stupid4(); UPDATE trigger_test SET v = 'null' WHERE i = 0; ERROR: TD["new"] deleted, cannot modify row -CONTEXT: PL/Python function "stupid4" +CONTEXT: while modifying trigger row +PL/Python function "stupid4" DROP TRIGGER stupid_trigger4 ON trigger_test; -- TD not a dictionary CREATE FUNCTION stupid5() RETURNS trigger @@ -366,7 +367,8 @@ BEFORE UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE stupid5(); UPDATE trigger_test SET v = 'null' WHERE i = 0; ERROR: TD["new"] is not a dictionary -CONTEXT: PL/Python function "stupid5" +CONTEXT: while modifying trigger row +PL/Python function "stupid5" DROP TRIGGER stupid_trigger5 ON trigger_test; -- TD not having string keys CREATE FUNCTION stupid6() RETURNS trigger @@ -379,7 +381,8 @@ BEFORE UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE stupid6(); UPDATE trigger_test SET v = 'null' WHERE i = 0; ERROR: TD["new"] dictionary key at ordinal position 0 is not a string -CONTEXT: PL/Python function "stupid6" +CONTEXT: while modifying trigger row +PL/Python function "stupid6" DROP TRIGGER stupid_trigger6 ON trigger_test; -- TD keys not corresponding to row columns CREATE FUNCTION stupid7() RETURNS trigger @@ -392,7 +395,8 @@ BEFORE UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE stupid7(); UPDATE trigger_test SET v = 'null' WHERE i = 0; ERROR: key "a" found in TD["new"] does not exist as a column in the triggering row -CONTEXT: PL/Python function "stupid7" +CONTEXT: while modifying trigger row +PL/Python function "stupid7" DROP TRIGGER stupid_trigger7 ON trigger_test; -- calling a trigger function directly SELECT stupid7(); diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out index 476f32974be4274859a472492959149479ad6442..19b3c9e47a1a080b620a3c60775ec6d59b1d283b 100644 --- a/src/pl/plpython/expected/plpython_types.out +++ b/src/pl/plpython/expected/plpython_types.out @@ -332,7 +332,8 @@ SELECT * FROM test_type_conversion_uint2(100::uint2, -50); INFO: (100, <type 'int'>) CONTEXT: PL/Python function "test_type_conversion_uint2" ERROR: value for domain uint2 violates check constraint "uint2_check" -CONTEXT: PL/Python function "test_type_conversion_uint2" +CONTEXT: while creating return value +PL/Python function "test_type_conversion_uint2" SELECT * FROM test_type_conversion_uint2(null, 1); INFO: (None, <type 'NoneType'>) CONTEXT: PL/Python function "test_type_conversion_uint2" @@ -360,11 +361,13 @@ SELECT * FROM test_type_conversion_bytea10('hello word', 'hello world'); INFO: ('\\x68656c6c6f20776f7264', <type 'str'>) CONTEXT: PL/Python function "test_type_conversion_bytea10" ERROR: value for domain bytea10 violates check constraint "bytea10_check" -CONTEXT: PL/Python function "test_type_conversion_bytea10" +CONTEXT: while creating return value +PL/Python function "test_type_conversion_bytea10" SELECT * FROM test_type_conversion_bytea10(null, 'hello word'); ERROR: value for domain bytea10 violates check constraint "bytea10_check" SELECT * FROM test_type_conversion_bytea10('hello word', null); INFO: ('\\x68656c6c6f20776f7264', <type 'str'>) CONTEXT: PL/Python function "test_type_conversion_bytea10" ERROR: value for domain bytea10 violates check constraint "bytea10_check" -CONTEXT: PL/Python function "test_type_conversion_bytea10" +CONTEXT: while creating return value +PL/Python function "test_type_conversion_bytea10" diff --git a/src/pl/plpython/expected/plpython_unicode.out b/src/pl/plpython/expected/plpython_unicode.out index ce19eb980c231f0f20f27d8cd54aa08a8e403b78..d3b6fd1db73aa37bb0ffc6dbec289ba1b7922112 100644 --- a/src/pl/plpython/expected/plpython_unicode.out +++ b/src/pl/plpython/expected/plpython_unicode.out @@ -24,13 +24,15 @@ rv = plpy.execute(plan, u"\\x80", 1) return rv[0]["testvalue1"] ' LANGUAGE plpythonu; SELECT unicode_return_error(); -ERROR: PL/Python: could not create string representation of Python object, while creating return value +ERROR: PL/Python: could not create string representation of Python object 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" +CONTEXT: while creating return value +PL/Python function "unicode_return_error" INSERT INTO unicode_test (testvalue) VALUES ('test'); -ERROR: PL/Python: could not compute string representation of Python object, while modifying trigger row +ERROR: PL/Python: could not create string representation of Python object 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" +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger_error" SELECT unicode_plan_error1(); WARNING: PL/Python: <class 'plpy.Error'>: unrecognized error in PLy_spi_execute_plan CONTEXT: PL/Python function "unicode_plan_error1" diff --git a/src/pl/plpython/expected/plpython_unicode_2.out b/src/pl/plpython/expected/plpython_unicode_2.out index 9280fe7dde9882c75a539b3945955efffd47decc..1f393fbef33214c7187760797bbcb2cc496e0b28 100644 --- a/src/pl/plpython/expected/plpython_unicode_2.out +++ b/src/pl/plpython/expected/plpython_unicode_2.out @@ -24,13 +24,15 @@ rv = plpy.execute(plan, u"\\x80", 1) return rv[0]["testvalue1"] ' LANGUAGE plpythonu; SELECT unicode_return_error(); -ERROR: PL/Python: could not create string representation of Python object, while creating return value +ERROR: PL/Python: could not create string representation of Python object DETAIL: exceptions.UnicodeError: ASCII encoding error: ordinal not in range(128) -CONTEXT: PL/Python function "unicode_return_error" +CONTEXT: while creating return value +PL/Python function "unicode_return_error" INSERT INTO unicode_test (testvalue) VALUES ('test'); -ERROR: PL/Python: could not compute string representation of Python object, while modifying trigger row +ERROR: PL/Python: could not create string representation of Python object DETAIL: exceptions.UnicodeError: ASCII encoding error: ordinal not in range(128) -CONTEXT: PL/Python function "unicode_trigger_error" +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger_error" SELECT unicode_plan_error1(); WARNING: PL/Python: plpy.Error: unrecognized error in PLy_spi_execute_plan CONTEXT: PL/Python function "unicode_plan_error1" diff --git a/src/pl/plpython/expected/plpython_unicode_3.out b/src/pl/plpython/expected/plpython_unicode_3.out index f058e2b098855b38f55d14ac2c25573be25e829e..620f9f57906360b6bacb4d72bef89ef1332c54a7 100644 --- a/src/pl/plpython/expected/plpython_unicode_3.out +++ b/src/pl/plpython/expected/plpython_unicode_3.out @@ -24,13 +24,15 @@ rv = plpy.execute(plan, u"\\x80", 1) return rv[0]["testvalue1"] ' LANGUAGE plpythonu; SELECT unicode_return_error(); -ERROR: PL/Python: could not create string representation of Python object, while creating return value +ERROR: PL/Python: could not create string representation of Python object 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" +CONTEXT: while creating return value +PL/Python function "unicode_return_error" INSERT INTO unicode_test (testvalue) VALUES ('test'); -ERROR: PL/Python: could not compute string representation of Python object, while modifying trigger row +ERROR: PL/Python: could not create string representation of Python object 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" +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger_error" SELECT unicode_plan_error1(); WARNING: PL/Python: plpy.Error: unrecognized error in PLy_spi_execute_plan CONTEXT: PL/Python function "unicode_plan_error1" diff --git a/src/pl/plpython/expected/plpython_void.out b/src/pl/plpython/expected/plpython_void.out index d067de06c061a2d85fe94a88ecdf080f957e70be..1080d12d6b257439f8f041a880463ac1e3e91c27 100644 --- a/src/pl/plpython/expected/plpython_void.out +++ b/src/pl/plpython/expected/plpython_void.out @@ -20,7 +20,8 @@ SELECT test_void_func1(), test_void_func1() IS NULL AS "is null"; 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" +CONTEXT: while creating return value +PL/Python function "test_void_func2" SELECT test_return_none(), test_return_none() IS NULL AS "is null"; test_return_none | is null ------------------+--------- diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index eec0288e493fcdc0cf4a593e84643eaf289ca064..4aba4ba95adf804ff2861d6f7b885c04bedc16c6 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -1,7 +1,7 @@ /********************************************************************** * plpython.c - python as a procedural language for PostgreSQL * - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.126 2009/08/25 08:14:42 petere Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.127 2009/08/25 12:44:59 petere Exp $ * ********************************************************************* */ @@ -339,6 +339,20 @@ plpython_error_callback(void *arg) errcontext("PL/Python function \"%s\"", PLy_procedure_name(PLy_curr_procedure)); } +static void +plpython_trigger_error_callback(void *arg) +{ + if (PLy_curr_procedure) + errcontext("while modifying trigger row"); +} + +static void +plpython_return_error_callback(void *arg) +{ + if (PLy_curr_procedure) + errcontext("while creating return value"); +} + Datum plpython_call_handler(PG_FUNCTION_ARGS) { @@ -506,6 +520,11 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, Datum *volatile modvalues; char *volatile modnulls; TupleDesc tupdesc; + ErrorContextCallback plerrcontext; + + plerrcontext.callback = plpython_trigger_error_callback; + plerrcontext.previous = error_context_stack; + error_context_stack = &plerrcontext; plntup = plkeys = platt = plval = plstr = NULL; modattrs = NULL; @@ -563,7 +582,7 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, { plstr = PyObject_Str(plval); if (!plstr) - PLy_elog(ERROR, "could not compute string representation of Python object, while modifying trigger row"); + PLy_elog(ERROR, "could not create string representation of Python object"); src = PyString_AsString(plstr); modvalues[i] = @@ -620,6 +639,8 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, pfree(modvalues); pfree(modnulls); + error_context_stack = plerrcontext.previous; + return rtup; } @@ -811,6 +832,7 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc) PyObject *volatile plrv = NULL; PyObject *volatile plrv_so = NULL; char *plrv_sc; + ErrorContextCallback plerrcontext; PG_TRY(); { @@ -901,6 +923,10 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc) } } + plerrcontext.callback = plpython_return_error_callback; + plerrcontext.previous = error_context_stack; + error_context_stack = &plerrcontext; + /* * If the function is declared to return void, the Python return value * must be None. For void-returning functions, we also treat a None @@ -959,7 +985,7 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc) fcinfo->isnull = false; plrv_so = PyObject_Str(plrv); if (!plrv_so) - PLy_elog(ERROR, "could not create string representation of Python object, while creating return value"); + PLy_elog(ERROR, "could not create string representation of Python object"); plrv_sc = PyString_AsString(plrv_so); rv = InputFunctionCall(&proc->result.out.d.typfunc, plrv_sc, @@ -977,6 +1003,8 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc) } PG_END_TRY(); + error_context_stack = plerrcontext.previous; + Py_XDECREF(plargs); Py_DECREF(plrv); Py_XDECREF(plrv_so);