From a3a8f237bdac86904053190d0f3b3c541e843456 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 28 Jul 2008 18:45:05 +0000 Subject: [PATCH] Update 8.1 and 8.0 plpython to work with Python 2.5. This backports several fixes made during the 8.2 development cycle, but not backported at the time for lack of confidence in the new coding. I didn't touch 7.4 because it has more problems than this: the configure probe for Python fails. --- src/pl/plpython/expected/plpython_error_3.out | 38 +++++++ .../plpython/expected/plpython_function.out | 1 - src/pl/plpython/plpython.c | 98 +++++++++++-------- src/pl/plpython/sql/plpython_function.sql | 1 - 4 files changed, 95 insertions(+), 43 deletions(-) create mode 100644 src/pl/plpython/expected/plpython_error_3.out diff --git a/src/pl/plpython/expected/plpython_error_3.out b/src/pl/plpython/expected/plpython_error_3.out new file mode 100644 index 00000000000..3cde9bf6ac9 --- /dev/null +++ b/src/pl/plpython/expected/plpython_error_3.out @@ -0,0 +1,38 @@ +-- test error handling, i forgot to restore Warn_restart in +-- the trigger handler once. the errors and subsequent core dump were +-- interesting. +SELECT invalid_type_uncaught('rick'); +WARNING: plpython: in function invalid_type_uncaught: +DETAIL: : Unknown error in PLy_spi_prepare +ERROR: type "test" does not exist +SELECT invalid_type_caught('rick'); +WARNING: plpython: in function invalid_type_caught: +DETAIL: : Unknown error in PLy_spi_prepare +ERROR: type "test" does not exist +SELECT invalid_type_reraised('rick'); +WARNING: plpython: in function invalid_type_reraised: +DETAIL: : Unknown error in PLy_spi_prepare +ERROR: type "test" does not exist +SELECT valid_type('rick'); + valid_type +------------ + +(1 row) + +-- +-- Test Unicode error handling. +-- +SELECT unicode_return_error(); +ERROR: plpython: function "unicode_return_error" could not create return value +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +INSERT INTO unicode_test (testvalue) VALUES ('test'); +ERROR: plpython: function "unicode_trigger_error" could not modify tuple +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +SELECT unicode_plan_error1(); +WARNING: plpython: in function unicode_plan_error1: +DETAIL: : Unknown error in PLy_spi_execute_plan +ERROR: plpython: function "unicode_plan_error1" could not execute plan +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +SELECT unicode_plan_error2(); +ERROR: plpython: function "unicode_plan_error2" could not execute plan +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) diff --git a/src/pl/plpython/expected/plpython_function.out b/src/pl/plpython/expected/plpython_function.out index 516d0576899..1161e1165d0 100644 --- a/src/pl/plpython/expected/plpython_function.out +++ b/src/pl/plpython/expected/plpython_function.out @@ -49,7 +49,6 @@ CREATE FUNCTION import_succeed() returns text import sha import string import time - import whrandom except Exception, ex: plpy.notice("import failed -- %s" % str(ex)) return "failed, that wasn''t supposed to happen" diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 2464e335b2b..98b7dfbc3b3 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -29,12 +29,22 @@ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.5 2007/11/23 01:47:12 alvherre Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.6 2008/07/28 18:45:05 tgl Exp $ * ********************************************************************* */ #include + +/* + * Py_ssize_t compat for Python <= 2.4 + */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + #include "postgres.h" /* system stuff */ @@ -1541,11 +1551,11 @@ static void PLy_result_dealloc(PyObject *); static PyObject *PLy_result_getattr(PyObject *, char *); static PyObject *PLy_result_nrows(PyObject *, PyObject *); static PyObject *PLy_result_status(PyObject *, PyObject *); -static int PLy_result_length(PyObject *); -static PyObject *PLy_result_item(PyObject *, int); -static PyObject *PLy_result_slice(PyObject *, int, int); -static int PLy_result_ass_item(PyObject *, int, PyObject *); -static int PLy_result_ass_slice(PyObject *, int, int, PyObject *); +static Py_ssize_t PLy_result_length(PyObject *); +static PyObject *PLy_result_item(PyObject *, Py_ssize_t); +static PyObject *PLy_result_slice(PyObject *, Py_ssize_t, Py_ssize_t); +static int PLy_result_ass_item(PyObject *, Py_ssize_t, PyObject *); +static int PLy_result_ass_slice(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); static PyObject *PLy_spi_prepare(PyObject *, PyObject *); @@ -1565,9 +1575,9 @@ static PyTypeObject PLy_PlanType = { /* * methods */ - (destructor) PLy_plan_dealloc, /* tp_dealloc */ + PLy_plan_dealloc, /* tp_dealloc */ 0, /* tp_print */ - (getattrfunc) PLy_plan_getattr, /* tp_getattr */ + PLy_plan_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ @@ -1580,7 +1590,7 @@ static PyTypeObject PLy_PlanType = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - 0, /* tp_xxx4 */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ PLy_plan_doc, /* tp_doc */ }; @@ -1589,15 +1599,14 @@ static PyMethodDef PLy_plan_methods[] = { {NULL, NULL, 0, NULL} }; - static PySequenceMethods PLy_result_as_sequence = { - (inquiry) PLy_result_length, /* sq_length */ - (binaryfunc) 0, /* sq_concat */ - (intargfunc) 0, /* sq_repeat */ - (intargfunc) PLy_result_item, /* sq_item */ - (intintargfunc) PLy_result_slice, /* sq_slice */ - (intobjargproc) PLy_result_ass_item, /* sq_ass_item */ - (intintobjargproc) PLy_result_ass_slice, /* sq_ass_slice */ + PLy_result_length, /* sq_length */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + PLy_result_item, /* sq_item */ + PLy_result_slice, /* sq_slice */ + PLy_result_ass_item, /* sq_ass_item */ + PLy_result_ass_slice, /* sq_ass_slice */ }; static PyTypeObject PLy_ResultType = { @@ -1610,9 +1619,9 @@ static PyTypeObject PLy_ResultType = { /* * methods */ - (destructor) PLy_result_dealloc, /* tp_dealloc */ + PLy_result_dealloc, /* tp_dealloc */ 0, /* tp_print */ - (getattrfunc) PLy_result_getattr, /* tp_getattr */ + PLy_result_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ @@ -1625,7 +1634,7 @@ static PyTypeObject PLy_ResultType = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - 0, /* tp_xxx4 */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ PLy_result_doc, /* tp_doc */ }; @@ -1698,7 +1707,7 @@ PLy_plan_dealloc(PyObject * arg) PLy_free(ob->args); } - PyMem_DEL(arg); + arg->ob_type->tp_free(arg); } @@ -1753,7 +1762,7 @@ PLy_result_dealloc(PyObject * arg) Py_XDECREF(ob->rows); Py_XDECREF(ob->status); - PyMem_DEL(ob); + arg->ob_type->tp_free(arg); } static PyObject * @@ -1780,7 +1789,7 @@ PLy_result_status(PyObject * self, PyObject * args) return ob->status; } -static int +static Py_ssize_t PLy_result_length(PyObject * arg) { PLyResultObject *ob = (PLyResultObject *) arg; @@ -1789,7 +1798,7 @@ PLy_result_length(PyObject * arg) } static PyObject * -PLy_result_item(PyObject * arg, int idx) +PLy_result_item(PyObject * arg, Py_ssize_t idx) { PyObject *rv; PLyResultObject *ob = (PLyResultObject *) arg; @@ -1801,7 +1810,7 @@ PLy_result_item(PyObject * arg, int idx) } static int -PLy_result_ass_item(PyObject * arg, int idx, PyObject * item) +PLy_result_ass_item(PyObject * arg, Py_ssize_t idx, PyObject * item) { int rv; PLyResultObject *ob = (PLyResultObject *) arg; @@ -1812,7 +1821,7 @@ PLy_result_ass_item(PyObject * arg, int idx, PyObject * item) } static PyObject * -PLy_result_slice(PyObject * arg, int lidx, int hidx) +PLy_result_slice(PyObject * arg, Py_ssize_t lidx, Py_ssize_t hidx) { PyObject *rv; PLyResultObject *ob = (PLyResultObject *) arg; @@ -1825,7 +1834,7 @@ PLy_result_slice(PyObject * arg, int lidx, int hidx) } static int -PLy_result_ass_slice(PyObject * arg, int lidx, int hidx, PyObject * slice) +PLy_result_ass_slice(PyObject * arg, Py_ssize_t lidx, Py_ssize_t hidx, PyObject * slice) { int rv; PLyResultObject *ob = (PLyResultObject *) arg; @@ -2036,13 +2045,14 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, long limit) PG_TRY(); { char *nulls = palloc(nargs * sizeof(char)); + volatile int j; - for (i = 0; i < nargs; i++) + for (j = 0; j < nargs; j++) { PyObject *elem, *so; - elem = PySequence_GetItem(list, i); + elem = PySequence_GetItem(list, j); if (elem != Py_None) { so = PyObject_Str(elem); @@ -2055,10 +2065,10 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, long limit) { char *sv = PyString_AsString(so); - plan->values[i] = - FunctionCall3(&(plan->args[i].out.d.typfunc), + plan->values[j] = + FunctionCall3(&(plan->args[j].out.d.typfunc), CStringGetDatum(sv), - ObjectIdGetDatum(plan->args[i].out.d.typioparam), + ObjectIdGetDatum(plan->args[j].out.d.typioparam), Int32GetDatum(-1)); } PG_CATCH(); @@ -2069,13 +2079,13 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, long limit) PG_END_TRY(); Py_DECREF(so); - nulls[i] = ' '; + nulls[j] = ' '; } else { Py_DECREF(elem); - plan->values[i] = (Datum) 0; - nulls[i] = 'n'; + plan->values[j] = (Datum) 0; + nulls[j] = 'n'; } } @@ -2086,6 +2096,8 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, long limit) } PG_CATCH(); { + int k; + MemoryContextSwitchTo(oldcontext); PLy_error_in_progress = CopyErrorData(); FlushErrorState(); @@ -2093,13 +2105,13 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, long limit) /* * cleanup plan->values array */ - for (i = 0; i < nargs; i++) + for (k = 0; k < nargs; k++) { - if (!plan->args[i].out.d.typbyval && - (plan->values[i] != (Datum) NULL)) + if (!plan->args[k].out.d.typbyval && + (plan->values[k] != (Datum) NULL)) { - pfree(DatumGetPointer(plan->values[i])); - plan->values[i] = (Datum) NULL; + pfree(DatumGetPointer(plan->values[k])); + plan->values[k] = (Datum) NULL; } } @@ -2319,7 +2331,11 @@ PLy_init_plpy(void) /* * initialize plpy module */ - PLy_PlanType.ob_type = PLy_ResultType.ob_type = &PyType_Type; + if (PyType_Ready(&PLy_PlanType) < 0) + elog(ERROR, "could not init PLy_PlanType"); + if (PyType_Ready(&PLy_ResultType) < 0) + elog(ERROR, "could not init PLy_ResultType"); + plpy = Py_InitModule("plpy", PLy_methods); plpy_dict = PyModule_GetDict(plpy); diff --git a/src/pl/plpython/sql/plpython_function.sql b/src/pl/plpython/sql/plpython_function.sql index e3ec2afe014..70e681d42c1 100644 --- a/src/pl/plpython/sql/plpython_function.sql +++ b/src/pl/plpython/sql/plpython_function.sql @@ -58,7 +58,6 @@ CREATE FUNCTION import_succeed() returns text import sha import string import time - import whrandom except Exception, ex: plpy.notice("import failed -- %s" % str(ex)) return "failed, that wasn''t supposed to happen" -- 2.39.5