]> granicus.if.org Git - postgresql/commitdiff
Update 8.1 and 8.0 plpython to work with Python 2.5. This backports several
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Jul 2008 18:45:05 +0000 (18:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Jul 2008 18:45:05 +0000 (18:45 +0000)
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 [new file with mode: 0644]
src/pl/plpython/expected/plpython_function.out
src/pl/plpython/plpython.c
src/pl/plpython/sql/plpython_function.sql

diff --git a/src/pl/plpython/expected/plpython_error_3.out b/src/pl/plpython/expected/plpython_error_3.out
new file mode 100644 (file)
index 0000000..3cde9bf
--- /dev/null
@@ -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:  <class 'plpy.SPIError'>: 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:  <class 'plpy.SPIError'>: 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:  <class 'plpy.SPIError'>: 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:  <type 'exceptions.UnicodeEncodeError'>: '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:  <type 'exceptions.UnicodeEncodeError'>: '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:  <class 'plpy.Error'>: Unknown error in PLy_spi_execute_plan
+ERROR:  plpython: function "unicode_plan_error1" could not execute plan
+DETAIL:  <type 'exceptions.UnicodeEncodeError'>: '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:  <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)
index 516d0576899bfa95d94a926c7121ee4b05293d61..1161e1165d0082ae4d8ed205cb95c1556edc68c2 100644 (file)
@@ -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"
index 2464e335b2ba989c713a8321c2f9bde7191a93fd..98b7dfbc3b31160dfe9df08cff61931a9efff2c0 100644 (file)
  * 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 <Python.h>
+
+/*
+ * 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);
 
index e3ec2afe01481e4cd4e396aed895bc0e3459fb4c..70e681d42c1ca9f88a7daf142c75c6f643adad6f 100644 (file)
@@ -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"