Hi,
there seems to be a problem in the way we add exceptions to the plpy
module in PL/Python compiled with Python 3k.
Try this: DO $$ plpy.SPIError $$ language plpython3u;
I'm not a Python 3 expert, but I nicked some code from the Internet and
came up with this patch (passes regression tests on both Python 2 and 3).
The funny thing is that it never blew up earlier, because we only used
plpy.SPIError in except: blocks that weren't even executed, as errors in
plpy.execute just terminate the function.
With my changes they turn into catchable exceptions, and so accessing
plpy.SPIError in Python 3 becomes essential.
BTW: do we have any buildfarm animal that uses Python 3?
Cheers,
Jan
*** src/pl/plpython/expected/plpython_test.out
--- src/pl/plpython/expected/plpython_test.out 2010-12-18 18:46:17.000000000 +0100
***************
*** 35,40 ****
--- 35,53 ----
willem doe => {fname: willem, lname: doe, userid: 3, username: w_doe}
(3 rows)
+ -- check module contents
+ CREATE FUNCTION module_contents() RETURNS text AS
+ $$
+ contents = dir(plpy)
+ contents.sort()
+ return ", ".join(contents)
+ $$ LANGUAGE plpythonu;
+ select module_contents();
+ module_contents
+ ---------------------------------------------------------------------------------------------------------------------------
+ Error, Fatal, SPIError, __doc__, __name__, __package__, debug, error, execute, fatal, info, log, notice, prepare, warning
+ (1 row)
+
CREATE FUNCTION elog_test() RETURNS void
AS $$
plpy.debug('debug')
*** src/pl/plpython/plpython.c
--- src/pl/plpython/plpython.c 2010-12-18 18:39:00.000000000 +0100
***************
*** 3204,3209 ****
--- 3204,3238 ----
/*
+ * Exception initialization
+ */
+
+ static void
+ PLy_initialize_exceptions(PyObject *plpy)
+ {
+ #if PY_MAJOR_VERSION < 3
+ PyObject *plpy_dict = PyModule_GetDict(plpy);
+ #endif
+
+ PLy_exc_error = PyErr_NewException("plpy.Error", NULL, NULL);
+ PLy_exc_fatal = PyErr_NewException("plpy.Fatal", NULL, NULL);
+ PLy_exc_spi_error = PyErr_NewException("plpy.SPIError", NULL, NULL);
+
+ #if PY_MAJOR_VERSION >= 3
+ Py_INCREF(PLy_exc_error);
+ PyModule_AddObject(plpy, "Error", PLy_exc_error);
+ Py_INCREF(PLy_exc_fatal);
+ PyModule_AddObject(plpy, "Fatal", PLy_exc_fatal);
+ Py_INCREF(PLy_exc_spi_error);
+ PyModule_AddObject(plpy, "SPIError", PLy_exc_spi_error);
+ #else
+ PyDict_SetItemString(plpy_dict, "Error", PLy_exc_error);
+ PyDict_SetItemString(plpy_dict, "Fatal", PLy_exc_fatal);
+ PyDict_SetItemString(plpy_dict, "SPIError", PLy_exc_spi_error);
+ #endif
+ }
+
+ /*
* language handler and interpreter initialization
*/
***************
*** 3211,3217 ****
static PyMODINIT_FUNC
PyInit_plpy(void)
{
! return PyModule_Create(&PLy_module);
}
#endif
--- 3240,3254 ----
static PyMODINIT_FUNC
PyInit_plpy(void)
{
! PyObject *m;
!
! m = PyModule_Create(&PLy_module);
! if (m == NULL)
! return NULL;
!
! PLy_initialize_exceptions(m);
!
! return m;
}
#endif
***************
*** 3290,3297 ****
PyObject *main_mod,
*main_dict,
*plpy_mod;
! PyObject *plpy,
! *plpy_dict;
/*
* initialize plpy module
--- 3327,3333 ----
PyObject *main_mod,
*main_dict,
*plpy_mod;
! PyObject *plpy;
/*
* initialize plpy module
***************
*** 3305,3322 ****
plpy = PyModule_Create(&PLy_module);
#else
plpy = Py_InitModule("plpy", PLy_methods);
#endif
- plpy_dict = PyModule_GetDict(plpy);
/* PyDict_SetItemString(plpy, "PlanType", (PyObject *) &PLy_PlanType); */
- PLy_exc_error = PyErr_NewException("plpy.Error", NULL, NULL);
- PLy_exc_fatal = PyErr_NewException("plpy.Fatal", NULL, NULL);
- PLy_exc_spi_error = PyErr_NewException("plpy.SPIError", NULL, NULL);
- PyDict_SetItemString(plpy_dict, "Error", PLy_exc_error);
- PyDict_SetItemString(plpy_dict, "Fatal", PLy_exc_fatal);
- PyDict_SetItemString(plpy_dict, "SPIError", PLy_exc_spi_error);
-
/*
* initialize main module, and add plpy
*/
--- 3341,3352 ----
plpy = PyModule_Create(&PLy_module);
#else
plpy = Py_InitModule("plpy", PLy_methods);
+ /* for Python 3 we initialized the exceptions in PyInit_plpy */
+ PLy_initialize_exceptions(plpy);
#endif
/* PyDict_SetItemString(plpy, "PlanType", (PyObject *) &PLy_PlanType); */
/*
* initialize main module, and add plpy
*/
*** src/pl/plpython/sql/plpython_test.sql
--- src/pl/plpython/sql/plpython_test.sql 2010-12-18 18:44:19.000000000 +0100
***************
*** 25,30 ****
--- 25,39 ----
select argument_test_one(users, fname, lname) from users where lname = 'doe' order by 1;
+ -- check module contents
+ CREATE FUNCTION module_contents() RETURNS text AS
+ $$
+ contents = dir(plpy)
+ contents.sort()
+ return ", ".join(contents)
+ $$ LANGUAGE plpythonu;
+
+ select module_contents();
CREATE FUNCTION elog_test() RETURNS void
AS $$
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers