Clean up plpython error reporting so that its regression test passes

with some amount of cleanliness.  I see no need to report the internal
Python name rather than the SQL procedure name in error tracebacks.
This commit is contained in:
Tom Lane 2003-01-31 22:25:14 +00:00
parent 9d00798720
commit 6f49703f0e
3 changed files with 41 additions and 31 deletions

View File

@ -1,12 +1,15 @@
SELECT invalid_type_uncaught('rick'); SELECT invalid_type_uncaught('rick');
WARNING: plpython: in function __plpython_procedure_invalid_type_uncaught_49801: WARNING: plpython: in function invalid_type_uncaught:
plpy.SPIError: Cache lookup for type `test' failed. plpy.SPIError: Unknown error in PLy_spi_prepare.
ERROR: Type "test" does not exist
SELECT invalid_type_caught('rick'); SELECT invalid_type_caught('rick');
WARNING: plpython: in function __plpython_procedure_invalid_type_caught_49802: WARNING: plpython: in function invalid_type_caught:
plpy.SPIError: Cache lookup for type `test' failed. plpy.SPIError: Unknown error in PLy_spi_prepare.
ERROR: Type "test" does not exist
SELECT invalid_type_reraised('rick'); SELECT invalid_type_reraised('rick');
WARNING: plpython: in function __plpython_procedure_invalid_type_reraised_49803: WARNING: plpython: in function invalid_type_reraised:
plpy.SPIError: Cache lookup for type `test' failed. plpy.SPIError: Unknown error in PLy_spi_prepare.
ERROR: Type "test" does not exist
SELECT valid_type('rick'); SELECT valid_type('rick');
valid_type valid_type
------------ ------------
@ -14,20 +17,20 @@ SELECT valid_type('rick');
(1 row) (1 row)
SELECT read_file('/etc/passwd'); SELECT read_file('/etc/passwd');
ERROR: plpython: Call of function `__plpython_procedure_read_file_49809' failed. ERROR: plpython: Call of function `read_file' failed.
exceptions.IOError: can't open files in restricted mode exceptions.IOError: can't open files in restricted mode
SELECT write_file('/tmp/plpython','This is very bad'); SELECT write_file('/tmp/plpython','This is very bad');
ERROR: plpython: Call of function `__plpython_procedure_write_file_49810' failed. ERROR: plpython: Call of function `write_file' failed.
exceptions.IOError: can't open files in restricted mode exceptions.IOError: can't open files in restricted mode
SELECT getpid(); SELECT getpid();
ERROR: plpython: Call of function `__plpython_procedure_getpid_49811' failed. ERROR: plpython: Call of function `getpid' failed.
exceptions.AttributeError: getpid exceptions.AttributeError: 'module' object has no attribute 'getpid'
SELECT uname(); SELECT uname();
ERROR: plpython: Call of function `__plpython_procedure_uname_49812' failed. ERROR: plpython: Call of function `uname' failed.
exceptions.AttributeError: uname exceptions.AttributeError: 'module' object has no attribute 'uname'
SELECT sys_exit(); SELECT sys_exit();
ERROR: plpython: Call of function `__plpython_procedure_sys_exit_49813' failed. ERROR: plpython: Call of function `sys_exit' failed.
exceptions.AttributeError: exit exceptions.AttributeError: 'module' object has no attribute 'exit'
SELECT sys_argv(); SELECT sys_argv();
sys_argv sys_argv
---------------- ----------------

View File

@ -29,7 +29,7 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.27 2002/11/22 16:25:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.28 2003/01/31 22:25:13 tgl Exp $
* *
********************************************************************* *********************************************************************
*/ */
@ -127,7 +127,8 @@ typedef struct PLyTypeInfo
*/ */
typedef struct PLyProcedure typedef struct PLyProcedure
{ {
char *proname; char *proname; /* SQL name of procedure */
char *pyname; /* Python name of procedure */
TransactionId fn_xmin; TransactionId fn_xmin;
CommandId fn_cmin; CommandId fn_cmin;
PLyTypeInfo result; /* also used to store info for trigger PLyTypeInfo result; /* also used to store info for trigger
@ -1050,7 +1051,7 @@ static PLyProcedure *
PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger, PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
HeapTuple procTup, char *key) HeapTuple procTup, char *key)
{ {
char procName[256]; char procName[NAMEDATALEN+256];
DECLARE_EXC(); DECLARE_EXC();
Form_pg_proc procStruct; Form_pg_proc procStruct;
@ -1073,8 +1074,10 @@ PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
elog(FATAL, "plpython: Procedure name would overrun buffer"); elog(FATAL, "plpython: Procedure name would overrun buffer");
proc = PLy_malloc(sizeof(PLyProcedure)); proc = PLy_malloc(sizeof(PLyProcedure));
proc->proname = PLy_malloc(strlen(procName) + 1); proc->proname = PLy_malloc(strlen(NameStr(procStruct->proname)) + 1);
strcpy(proc->proname, procName); strcpy(proc->proname, NameStr(procStruct->proname));
proc->pyname = PLy_malloc(strlen(procName) + 1);
strcpy(proc->pyname, procName);
proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data); proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
proc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data); proc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
PLy_typeinfo_init(&proc->result); PLy_typeinfo_init(&proc->result);
@ -1235,21 +1238,21 @@ PLy_procedure_compile(PLyProcedure * proc, const char *src)
/* /*
* insert the function code into the interpreter * insert the function code into the interpreter
*/ */
msrc = PLy_procedure_munge_source(proc->proname, src); msrc = PLy_procedure_munge_source(proc->pyname, src);
crv = PyObject_CallMethod(proc->interp, "r_exec", "s", msrc); crv = PyObject_CallMethod(proc->interp, "r_exec", "s", msrc);
free(msrc); free(msrc);
if ((crv != NULL) && (!PyErr_Occurred())) if ((crv != NULL) && (!PyErr_Occurred()))
{ {
int clen; int clen;
char call[256]; char call[NAMEDATALEN+256];
Py_DECREF(crv); Py_DECREF(crv);
/* /*
* compile a call to the function * compile a call to the function
*/ */
clen = snprintf(call, sizeof(call), "%s()", proc->proname); clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
if ((clen < 0) || (clen >= sizeof(call))) if ((clen < 0) || (clen >= sizeof(call)))
elog(ERROR, "plpython: string would overflow buffer."); elog(ERROR, "plpython: string would overflow buffer.");
proc->code = Py_CompileString(call, "<string>", Py_eval_input); proc->code = Py_CompileString(call, "<string>", Py_eval_input);
@ -1321,6 +1324,8 @@ PLy_procedure_delete(PLyProcedure * proc)
Py_XDECREF(proc->me); Py_XDECREF(proc->me);
if (proc->proname) if (proc->proname)
PLy_free(proc->proname); PLy_free(proc->proname);
if (proc->pyname)
PLy_free(proc->pyname);
for (i = 0; i < proc->nargs; i++) for (i = 0; i < proc->nargs; i++)
if (proc->args[i].is_rel == 1) if (proc->args[i].is_rel == 1)
{ {
@ -2748,9 +2753,12 @@ PLy_output(volatile int level, PyObject * self, PyObject * args)
} }
/* Get the last procedure name called by the backend ( the innermost, /*
* Get the last procedure name called by the backend ( the innermost,
* If a plpython procedure call calls the backend and the backend calls * If a plpython procedure call calls the backend and the backend calls
* another plpython procedure ) * another plpython procedure )
*
* NB: this returns SQL name, not the internal Python procedure name
*/ */
char * char *

View File

@ -30,8 +30,8 @@ echo -n "*** Running error handling tests."
psql -q -e $DBNAME < plpython_error.sql > error.output 2>&1 psql -q -e $DBNAME < plpython_error.sql > error.output 2>&1
echo " Done. ***" echo " Done. ***"
echo -n "*** Checking the results of the feature tests" echo -n "*** Checking the results of the feature tests."
if diff -u feature.expected feature.output > feature.diff 2>&1 ; then if diff -c feature.expected feature.output > feature.diff 2>&1 ; then
echo -n " passed!" echo -n " passed!"
else else
echo -n " failed! Please examine feature.diff." echo -n " failed! Please examine feature.diff."
@ -39,10 +39,9 @@ fi
echo " Done. ***" echo " Done. ***"
echo -n "*** Checking the results of the error handling tests." echo -n "*** Checking the results of the error handling tests."
diff -u error.expected error.output > error.diff 2>&1 if diff -c error.expected error.output > error.diff 2>&1 ; then
echo -n " passed!"
else
echo -n " failed! Please examine error.diff."
fi
echo " Done. ***" echo " Done. ***"
echo "*** You need to check the file error.diff and make sure that"
echo " any differences are due only to the oid encoded in the "
echo " python function name. ***"
# or write a fancier error checker...