PL/Python: Add cursor and execute methods to plan object
Instead of plan = plpy.prepare(...) res = plpy.execute(plan, ...) you can now write plan = plpy.prepare(...) res = plan.execute(...) or even res = plpy.prepare(...).execute(...) and similarly for the cursor() method. This is more in object oriented style, and makes the hybrid nature of the existing execute() function less confusing. Reviewed-by: Andrew Dunstan <andrew.dunstan@2ndquadrant.com>
This commit is contained in:
parent
090010f2ec
commit
70ec3f1f8f
|
@ -1046,6 +1046,14 @@ rv = plpy.execute(plan, ["name"], 5)
|
|||
The third argument is the optional row limit as before.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Alternatively, you can call the <function>execute</function> method on
|
||||
the plan object:
|
||||
<programlisting>
|
||||
rv = plan.execute(["name"], 5)
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Query parameters and result row fields are converted between PostgreSQL
|
||||
and Python data types as described in <xref linkend="plpython-data">.
|
||||
|
@ -1081,7 +1089,9 @@ $$ LANGUAGE plpythonu;
|
|||
as <literal>plpy.execute</literal> (except for the row limit) and returns
|
||||
a cursor object, which allows you to process large result sets in smaller
|
||||
chunks. As with <literal>plpy.execute</literal>, either a query string
|
||||
or a plan object along with a list of arguments can be used.
|
||||
or a plan object along with a list of arguments can be used, or
|
||||
the <function>cursor</function> function can be called as a method of
|
||||
the plan object.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1125,7 +1135,7 @@ $$ LANGUAGE plpythonu;
|
|||
CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$
|
||||
odd = 0
|
||||
plan = plpy.prepare("select num from largetable where num % $1 <> 0", ["integer"])
|
||||
rows = list(plpy.cursor(plan, [2]))
|
||||
rows = list(plpy.cursor(plan, [2])) # or: = list(plan.cursor([2]))
|
||||
|
||||
return len(rows)
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
|
|
@ -29,6 +29,19 @@ try:
|
|||
except Exception, ex:
|
||||
plpy.error(str(ex))
|
||||
return None
|
||||
'
|
||||
LANGUAGE plpythonu;
|
||||
CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS text
|
||||
AS
|
||||
'if "myplan" not in SD:
|
||||
q = "SELECT count(*) FROM users WHERE lname = $1"
|
||||
SD["myplan"] = plpy.prepare(q, [ "text" ])
|
||||
try:
|
||||
rv = SD["myplan"].execute([a])
|
||||
return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
|
||||
except Exception, ex:
|
||||
plpy.error(str(ex))
|
||||
return None
|
||||
'
|
||||
LANGUAGE plpythonu;
|
||||
CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
|
||||
|
@ -80,8 +93,8 @@ select spi_prepared_plan_test_one('doe');
|
|||
there are 3 does
|
||||
(1 row)
|
||||
|
||||
select spi_prepared_plan_test_one('smith');
|
||||
spi_prepared_plan_test_one
|
||||
select spi_prepared_plan_test_two('smith');
|
||||
spi_prepared_plan_test_two
|
||||
----------------------------
|
||||
there are 1 smiths
|
||||
(1 row)
|
||||
|
@ -372,7 +385,7 @@ plan = plpy.prepare(
|
|||
["text"])
|
||||
for row in plpy.cursor(plan, ["w"]):
|
||||
yield row['fname']
|
||||
for row in plpy.cursor(plan, ["j"]):
|
||||
for row in plan.cursor(["j"]):
|
||||
yield row['fname']
|
||||
$$ LANGUAGE plpythonu;
|
||||
CREATE FUNCTION cursor_plan_wrong_args() RETURNS SETOF text AS $$
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
|
||||
static PyObject *PLy_cursor_query(const char *query);
|
||||
static PyObject *PLy_cursor_plan(PyObject *ob, PyObject *args);
|
||||
static void PLy_cursor_dealloc(PyObject *arg);
|
||||
static PyObject *PLy_cursor_iternext(PyObject *self);
|
||||
static PyObject *PLy_cursor_fetch(PyObject *self, PyObject *args);
|
||||
|
@ -160,7 +159,7 @@ PLy_cursor_query(const char *query)
|
|||
return (PyObject *) cursor;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyObject *
|
||||
PLy_cursor_plan(PyObject *ob, PyObject *args)
|
||||
{
|
||||
PLyCursorObject *cursor;
|
||||
|
|
|
@ -19,5 +19,6 @@ typedef struct PLyCursorObject
|
|||
|
||||
extern void PLy_cursor_init_type(void);
|
||||
extern PyObject *PLy_cursor(PyObject *self, PyObject *args);
|
||||
extern PyObject *PLy_cursor_plan(PyObject *ob, PyObject *args);
|
||||
|
||||
#endif /* PLPY_CURSOROBJECT_H */
|
||||
|
|
|
@ -10,11 +10,15 @@
|
|||
|
||||
#include "plpy_planobject.h"
|
||||
|
||||
#include "plpy_cursorobject.h"
|
||||
#include "plpy_elog.h"
|
||||
#include "plpy_spi.h"
|
||||
#include "utils/memutils.h"
|
||||
|
||||
|
||||
static void PLy_plan_dealloc(PyObject *arg);
|
||||
static PyObject *PLy_plan_cursor(PyObject *self, PyObject *args);
|
||||
static PyObject *PLy_plan_execute(PyObject *self, PyObject *args);
|
||||
static PyObject *PLy_plan_status(PyObject *self, PyObject *args);
|
||||
|
||||
static char PLy_plan_doc[] = {
|
||||
|
@ -22,6 +26,8 @@ static char PLy_plan_doc[] = {
|
|||
};
|
||||
|
||||
static PyMethodDef PLy_plan_methods[] = {
|
||||
{"cursor", PLy_plan_cursor, METH_VARARGS, NULL},
|
||||
{"execute", PLy_plan_execute, METH_VARARGS, NULL},
|
||||
{"status", PLy_plan_status, METH_VARARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
@ -111,6 +117,31 @@ PLy_plan_dealloc(PyObject *arg)
|
|||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
PLy_plan_cursor(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *planargs = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|O", &planargs))
|
||||
return NULL;
|
||||
|
||||
return PLy_cursor_plan(self, planargs);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
PLy_plan_execute(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *list = NULL;
|
||||
long limit = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|Ol", &list, &limit))
|
||||
return NULL;
|
||||
|
||||
return PLy_spi_execute_plan(self, list, limit);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
PLy_plan_status(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
|
||||
static PyObject *PLy_spi_execute_query(char *query, long limit);
|
||||
static PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit);
|
||||
static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable,
|
||||
uint64 rows, int status);
|
||||
static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata);
|
||||
|
@ -193,7 +192,7 @@ PLy_spi_execute(PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyObject *
|
||||
PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
|
||||
{
|
||||
volatile int nargs;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
extern PyObject *PLy_spi_prepare(PyObject *self, PyObject *args);
|
||||
extern PyObject *PLy_spi_execute(PyObject *self, PyObject *args);
|
||||
extern PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit);
|
||||
|
||||
typedef struct PLyExceptionEntry
|
||||
{
|
||||
|
|
|
@ -37,6 +37,20 @@ return None
|
|||
'
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS text
|
||||
AS
|
||||
'if "myplan" not in SD:
|
||||
q = "SELECT count(*) FROM users WHERE lname = $1"
|
||||
SD["myplan"] = plpy.prepare(q, [ "text" ])
|
||||
try:
|
||||
rv = SD["myplan"].execute([a])
|
||||
return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
|
||||
except Exception, ex:
|
||||
plpy.error(str(ex))
|
||||
return None
|
||||
'
|
||||
LANGUAGE plpythonu;
|
||||
|
||||
CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
|
||||
AS
|
||||
'if "myplan" not in SD:
|
||||
|
@ -79,7 +93,7 @@ return a + r
|
|||
--
|
||||
select nested_call_one('pass this along');
|
||||
select spi_prepared_plan_test_one('doe');
|
||||
select spi_prepared_plan_test_one('smith');
|
||||
select spi_prepared_plan_test_two('smith');
|
||||
select spi_prepared_plan_test_nested('smith');
|
||||
|
||||
SELECT join_sequences(sequences) FROM sequences;
|
||||
|
@ -275,7 +289,7 @@ plan = plpy.prepare(
|
|||
["text"])
|
||||
for row in plpy.cursor(plan, ["w"]):
|
||||
yield row['fname']
|
||||
for row in plpy.cursor(plan, ["j"]):
|
||||
for row in plan.cursor(["j"]):
|
||||
yield row['fname']
|
||||
$$ LANGUAGE plpythonu;
|
||||
|
||||
|
|
Loading…
Reference in New Issue