Commit 983d1083 authored by Peter Eisentraut's avatar Peter Eisentraut

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.
parent 5dff9363
...@@ -111,3 +111,24 @@ SELECT join_sequences(sequences) FROM sequences ...@@ -111,3 +111,24 @@ SELECT join_sequences(sequences) FROM sequences
---------------- ----------------
(0 rows) (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)
/********************************************************************** /**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL * 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 *); ...@@ -2050,12 +2050,10 @@ static PyObject *PLy_fatal(PyObject *, PyObject *);
#define is_PLyPlanObject(x) ((x)->ob_type == &PLy_PlanType) #define is_PLyPlanObject(x) ((x)->ob_type == &PLy_PlanType)
static PyObject *PLy_plan_new(void); static PyObject *PLy_plan_new(void);
static void PLy_plan_dealloc(PyObject *); static void PLy_plan_dealloc(PyObject *);
static PyObject *PLy_plan_getattr(PyObject *, char *);
static PyObject *PLy_plan_status(PyObject *, PyObject *); static PyObject *PLy_plan_status(PyObject *, PyObject *);
static PyObject *PLy_result_new(void); static PyObject *PLy_result_new(void);
static void PLy_result_dealloc(PyObject *); static void PLy_result_dealloc(PyObject *);
static PyObject *PLy_result_getattr(PyObject *, char *);
static PyObject *PLy_result_nrows(PyObject *, PyObject *); static PyObject *PLy_result_nrows(PyObject *, PyObject *);
static PyObject *PLy_result_status(PyObject *, PyObject *); static PyObject *PLy_result_status(PyObject *, PyObject *);
static Py_ssize_t PLy_result_length(PyObject *); static Py_ssize_t PLy_result_length(PyObject *);
...@@ -2072,6 +2070,11 @@ static PyObject *PLy_spi_execute_plan(PyObject *, PyObject *, long); ...@@ -2072,6 +2070,11 @@ static PyObject *PLy_spi_execute_plan(PyObject *, PyObject *, long);
static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *, int, int); 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 = { static PyTypeObject PLy_PlanType = {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /* ob_size */ 0, /* ob_size */
...@@ -2084,7 +2087,7 @@ static PyTypeObject PLy_PlanType = { ...@@ -2084,7 +2087,7 @@ static PyTypeObject PLy_PlanType = {
*/ */
PLy_plan_dealloc, /* tp_dealloc */ PLy_plan_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
PLy_plan_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
0, /* tp_repr */ 0, /* tp_repr */
...@@ -2099,11 +2102,13 @@ static PyTypeObject PLy_PlanType = { ...@@ -2099,11 +2102,13 @@ static PyTypeObject PLy_PlanType = {
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
PLy_plan_doc, /* tp_doc */ PLy_plan_doc, /* tp_doc */
}; 0, /* tp_traverse */
0, /* tp_clear */
static PyMethodDef PLy_plan_methods[] = { 0, /* tp_richcompare */
{"status", PLy_plan_status, METH_VARARGS, NULL}, 0, /* tp_weaklistoffset */
{NULL, NULL, 0, NULL} 0, /* tp_iter */
0, /* tp_iternext */
PLy_plan_methods, /* tp_tpmethods */
}; };
static PySequenceMethods PLy_result_as_sequence = { static PySequenceMethods PLy_result_as_sequence = {
...@@ -2116,6 +2121,12 @@ static PySequenceMethods PLy_result_as_sequence = { ...@@ -2116,6 +2121,12 @@ static PySequenceMethods PLy_result_as_sequence = {
PLy_result_ass_slice, /* sq_ass_slice */ 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 = { static PyTypeObject PLy_ResultType = {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /* ob_size */ 0, /* ob_size */
...@@ -2128,7 +2139,7 @@ static PyTypeObject PLy_ResultType = { ...@@ -2128,7 +2139,7 @@ static PyTypeObject PLy_ResultType = {
*/ */
PLy_result_dealloc, /* tp_dealloc */ PLy_result_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
PLy_result_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
0, /* tp_repr */ 0, /* tp_repr */
...@@ -2143,12 +2154,13 @@ static PyTypeObject PLy_ResultType = { ...@@ -2143,12 +2154,13 @@ static PyTypeObject PLy_ResultType = {
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
PLy_result_doc, /* tp_doc */ PLy_result_doc, /* tp_doc */
}; 0, /* tp_traverse */
0, /* tp_clear */
static PyMethodDef PLy_result_methods[] = { 0, /* tp_richcompare */
{"nrows", PLy_result_nrows, METH_VARARGS, NULL}, 0, /* tp_weaklistoffset */
{"status", PLy_result_status, METH_VARARGS, NULL}, 0, /* tp_iter */
{NULL, NULL, 0, NULL} 0, /* tp_iternext */
PLy_result_methods, /* tp_tpmethods */
}; };
static PyMethodDef PLy_methods[] = { static PyMethodDef PLy_methods[] = {
...@@ -2217,12 +2229,6 @@ PLy_plan_dealloc(PyObject *arg) ...@@ -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 * static PyObject *
PLy_plan_status(PyObject *self, PyObject *args) PLy_plan_status(PyObject *self, PyObject *args)
{ {
...@@ -2270,12 +2276,6 @@ PLy_result_dealloc(PyObject *arg) ...@@ -2270,12 +2276,6 @@ PLy_result_dealloc(PyObject *arg)
arg->ob_type->tp_free(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 * static PyObject *
PLy_result_nrows(PyObject *self, PyObject *args) PLy_result_nrows(PyObject *self, PyObject *args)
{ {
......
...@@ -87,3 +87,21 @@ SELECT join_sequences(sequences) FROM sequences ...@@ -87,3 +87,21 @@ SELECT join_sequences(sequences) FROM sequences
WHERE join_sequences(sequences) ~* '^A'; WHERE join_sequences(sequences) ~* '^A';
SELECT join_sequences(sequences) FROM sequences SELECT join_sequences(sequences) FROM sequences
WHERE join_sequences(sequences) ~* '^B'; 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();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment