From 983d10833e62d8f6e79e09a060e4e539b3a916c5 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <peter_e@gmx.net> Date: Tue, 25 Aug 2009 08:14:42 +0000 Subject: [PATCH] Use generic attribute management in PL/Python Switch the implementation of the plan and result types to generic attribute management, as described at <http://docs.python.org/extending/newtypes.html>. This modernizes and simplifies the code a bit and prepares for Python 3.1, where the old way doesn't work anymore. --- src/pl/plpython/expected/plpython_spi.out | 21 +++++++++ src/pl/plpython/plpython.c | 56 +++++++++++------------ src/pl/plpython/sql/plpython_spi.sql | 18 ++++++++ 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/src/pl/plpython/expected/plpython_spi.out b/src/pl/plpython/expected/plpython_spi.out index 9cef3f2bb0b..9097262a48d 100644 --- a/src/pl/plpython/expected/plpython_spi.out +++ b/src/pl/plpython/expected/plpython_spi.out @@ -111,3 +111,24 @@ SELECT join_sequences(sequences) FROM sequences ---------------- (0 rows) +-- +-- plan and result objects +-- +CREATE FUNCTION result_nrows_test() RETURNS int +AS $$ +plan = plpy.prepare("SELECT 1 UNION SELECT 2") +plpy.info(plan.status()) # not really documented or useful +result = plpy.execute(plan) +if result.status() > 0: + return result.nrows() +else: + return None +$$ LANGUAGE plpythonu; +SELECT result_nrows_test(); +INFO: (True,) +CONTEXT: PL/Python function "result_nrows_test" + result_nrows_test +------------------- + 2 +(1 row) + diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index ee94b637fe7..eec0288e493 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.125 2009/08/14 13:12:21 petere Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.126 2009/08/25 08:14:42 petere Exp $ * ********************************************************************* */ @@ -2050,12 +2050,10 @@ static PyObject *PLy_fatal(PyObject *, PyObject *); #define is_PLyPlanObject(x) ((x)->ob_type == &PLy_PlanType) static PyObject *PLy_plan_new(void); static void PLy_plan_dealloc(PyObject *); -static PyObject *PLy_plan_getattr(PyObject *, char *); static PyObject *PLy_plan_status(PyObject *, PyObject *); static PyObject *PLy_result_new(void); 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 Py_ssize_t PLy_result_length(PyObject *); @@ -2072,6 +2070,11 @@ static PyObject *PLy_spi_execute_plan(PyObject *, PyObject *, long); static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *, int, int); +static PyMethodDef PLy_plan_methods[] = { + {"status", PLy_plan_status, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} +}; + static PyTypeObject PLy_PlanType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ @@ -2084,7 +2087,7 @@ static PyTypeObject PLy_PlanType = { */ PLy_plan_dealloc, /* tp_dealloc */ 0, /* tp_print */ - PLy_plan_getattr, /* tp_getattr */ + 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ @@ -2099,11 +2102,13 @@ static PyTypeObject PLy_PlanType = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ PLy_plan_doc, /* tp_doc */ -}; - -static PyMethodDef PLy_plan_methods[] = { - {"status", PLy_plan_status, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL} + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PLy_plan_methods, /* tp_tpmethods */ }; static PySequenceMethods PLy_result_as_sequence = { @@ -2116,6 +2121,12 @@ static PySequenceMethods PLy_result_as_sequence = { PLy_result_ass_slice, /* sq_ass_slice */ }; +static PyMethodDef PLy_result_methods[] = { + {"nrows", PLy_result_nrows, METH_VARARGS, NULL}, + {"status", PLy_result_status, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} +}; + static PyTypeObject PLy_ResultType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ @@ -2128,7 +2139,7 @@ static PyTypeObject PLy_ResultType = { */ PLy_result_dealloc, /* tp_dealloc */ 0, /* tp_print */ - PLy_result_getattr, /* tp_getattr */ + 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ @@ -2143,12 +2154,13 @@ static PyTypeObject PLy_ResultType = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ PLy_result_doc, /* tp_doc */ -}; - -static PyMethodDef PLy_result_methods[] = { - {"nrows", PLy_result_nrows, METH_VARARGS, NULL}, - {"status", PLy_result_status, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL} + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PLy_result_methods, /* tp_tpmethods */ }; static PyMethodDef PLy_methods[] = { @@ -2217,12 +2229,6 @@ PLy_plan_dealloc(PyObject *arg) } -static PyObject * -PLy_plan_getattr(PyObject *self, char *name) -{ - return Py_FindMethod(PLy_plan_methods, self, name); -} - static PyObject * PLy_plan_status(PyObject *self, PyObject *args) { @@ -2270,12 +2276,6 @@ PLy_result_dealloc(PyObject *arg) arg->ob_type->tp_free(arg); } -static PyObject * -PLy_result_getattr(PyObject *self, char *name) -{ - return Py_FindMethod(PLy_result_methods, self, name); -} - static PyObject * PLy_result_nrows(PyObject *self, PyObject *args) { diff --git a/src/pl/plpython/sql/plpython_spi.sql b/src/pl/plpython/sql/plpython_spi.sql index 2157569f4c7..b607cdb9397 100644 --- a/src/pl/plpython/sql/plpython_spi.sql +++ b/src/pl/plpython/sql/plpython_spi.sql @@ -87,3 +87,21 @@ SELECT join_sequences(sequences) FROM sequences WHERE join_sequences(sequences) ~* '^A'; SELECT join_sequences(sequences) FROM sequences WHERE join_sequences(sequences) ~* '^B'; + + +-- +-- plan and result objects +-- + +CREATE FUNCTION result_nrows_test() RETURNS int +AS $$ +plan = plpy.prepare("SELECT 1 UNION SELECT 2") +plpy.info(plan.status()) # not really documented or useful +result = plpy.execute(plan) +if result.status() > 0: + return result.nrows() +else: + return None +$$ LANGUAGE plpythonu; + +SELECT result_nrows_test(); -- GitLab