Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit70ec3f1

Browse files
committed
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 ofthe existing execute() function less confusing.Reviewed-by: Andrew Dunstan <andrew.dunstan@2ndquadrant.com>
1 parent090010f commit70ec3f1

File tree

8 files changed

+79
-11
lines changed

8 files changed

+79
-11
lines changed

‎doc/src/sgml/plpython.sgml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,14 @@ rv = plpy.execute(plan, ["name"], 5)
10461046
The third argument is the optional row limit as before.
10471047
</para>
10481048

1049+
<para>
1050+
Alternatively, you can call the <function>execute</function> method on
1051+
the plan object:
1052+
<programlisting>
1053+
rv = plan.execute(["name"], 5)
1054+
</programlisting>
1055+
</para>
1056+
10491057
<para>
10501058
Query parameters and result row fields are converted between PostgreSQL
10511059
and Python data types as described in <xref linkend="plpython-data">.
@@ -1081,7 +1089,9 @@ $$ LANGUAGE plpythonu;
10811089
as <literal>plpy.execute</literal> (except for the row limit) and returns
10821090
a cursor object, which allows you to process large result sets in smaller
10831091
chunks. As with <literal>plpy.execute</literal>, either a query string
1084-
or a plan object along with a list of arguments can be used.
1092+
or a plan object along with a list of arguments can be used, or
1093+
the <function>cursor</function> function can be called as a method of
1094+
the plan object.
10851095
</para>
10861096

10871097
<para>
@@ -1125,7 +1135,7 @@ $$ LANGUAGE plpythonu;
11251135
CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$
11261136
odd = 0
11271137
plan = plpy.prepare("select num from largetable where num % $1 &lt;&gt; 0", ["integer"])
1128-
rows = list(plpy.cursor(plan, [2]))
1138+
rows = list(plpy.cursor(plan, [2])) # or: = list(plan.cursor([2]))
11291139

11301140
return len(rows)
11311141
$$ LANGUAGE plpythonu;

‎src/pl/plpython/expected/plpython_spi.out

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ try:
2929
except Exception, ex:
3030
plpy.error(str(ex))
3131
return None
32+
'
33+
LANGUAGE plpythonu;
34+
CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS text
35+
AS
36+
'if "myplan" not in SD:
37+
q = "SELECT count(*) FROM users WHERE lname = $1"
38+
SD["myplan"] = plpy.prepare(q, [ "text" ])
39+
try:
40+
rv = SD["myplan"].execute([a])
41+
return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
42+
except Exception, ex:
43+
plpy.error(str(ex))
44+
return None
3245
'
3346
LANGUAGE plpythonu;
3447
CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
@@ -80,8 +93,8 @@ select spi_prepared_plan_test_one('doe');
8093
there are 3 does
8194
(1 row)
8295

83-
selectspi_prepared_plan_test_one('smith');
84-
spi_prepared_plan_test_one
96+
selectspi_prepared_plan_test_two('smith');
97+
spi_prepared_plan_test_two
8598
----------------------------
8699
there are 1 smiths
87100
(1 row)
@@ -372,7 +385,7 @@ plan = plpy.prepare(
372385
["text"])
373386
for row in plpy.cursor(plan, ["w"]):
374387
yield row['fname']
375-
for row inplpy.cursor(plan,["j"]):
388+
for row inplan.cursor(["j"]):
376389
yield row['fname']
377390
$$ LANGUAGE plpythonu;
378391
CREATE FUNCTION cursor_plan_wrong_args() RETURNS SETOF text AS $$

‎src/pl/plpython/plpy_cursorobject.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626

2727
staticPyObject*PLy_cursor_query(constchar*query);
28-
staticPyObject*PLy_cursor_plan(PyObject*ob,PyObject*args);
2928
staticvoidPLy_cursor_dealloc(PyObject*arg);
3029
staticPyObject*PLy_cursor_iternext(PyObject*self);
3130
staticPyObject*PLy_cursor_fetch(PyObject*self,PyObject*args);
@@ -160,7 +159,7 @@ PLy_cursor_query(const char *query)
160159
return (PyObject*)cursor;
161160
}
162161

163-
staticPyObject*
162+
PyObject*
164163
PLy_cursor_plan(PyObject*ob,PyObject*args)
165164
{
166165
PLyCursorObject*cursor;

‎src/pl/plpython/plpy_cursorobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ typedef struct PLyCursorObject
1919

2020
externvoidPLy_cursor_init_type(void);
2121
externPyObject*PLy_cursor(PyObject*self,PyObject*args);
22+
externPyObject*PLy_cursor_plan(PyObject*ob,PyObject*args);
2223

2324
#endif/* PLPY_CURSOROBJECT_H */

‎src/pl/plpython/plpy_planobject.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,24 @@
1010

1111
#include"plpy_planobject.h"
1212

13+
#include"plpy_cursorobject.h"
1314
#include"plpy_elog.h"
15+
#include"plpy_spi.h"
1416
#include"utils/memutils.h"
1517

1618

1719
staticvoidPLy_plan_dealloc(PyObject*arg);
20+
staticPyObject*PLy_plan_cursor(PyObject*self,PyObject*args);
21+
staticPyObject*PLy_plan_execute(PyObject*self,PyObject*args);
1822
staticPyObject*PLy_plan_status(PyObject*self,PyObject*args);
1923

2024
staticcharPLy_plan_doc[]= {
2125
"Store a PostgreSQL plan"
2226
};
2327

2428
staticPyMethodDefPLy_plan_methods[]= {
29+
{"cursor",PLy_plan_cursor,METH_VARARGS,NULL},
30+
{"execute",PLy_plan_execute,METH_VARARGS,NULL},
2531
{"status",PLy_plan_status,METH_VARARGS,NULL},
2632
{NULL,NULL,0,NULL}
2733
};
@@ -111,6 +117,31 @@ PLy_plan_dealloc(PyObject *arg)
111117
}
112118

113119

120+
staticPyObject*
121+
PLy_plan_cursor(PyObject*self,PyObject*args)
122+
{
123+
PyObject*planargs=NULL;
124+
125+
if (!PyArg_ParseTuple(args,"|O",&planargs))
126+
returnNULL;
127+
128+
returnPLy_cursor_plan(self,planargs);
129+
}
130+
131+
132+
staticPyObject*
133+
PLy_plan_execute(PyObject*self,PyObject*args)
134+
{
135+
PyObject*list=NULL;
136+
longlimit=0;
137+
138+
if (!PyArg_ParseTuple(args,"|Ol",&list,&limit))
139+
returnNULL;
140+
141+
returnPLy_spi_execute_plan(self,list,limit);
142+
}
143+
144+
114145
staticPyObject*
115146
PLy_plan_status(PyObject*self,PyObject*args)
116147
{

‎src/pl/plpython/plpy_spi.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131

3232
staticPyObject*PLy_spi_execute_query(char*query,longlimit);
33-
staticPyObject*PLy_spi_execute_plan(PyObject*ob,PyObject*list,longlimit);
3433
staticPyObject*PLy_spi_execute_fetch_result(SPITupleTable*tuptable,
3534
uint64rows,intstatus);
3635
staticvoidPLy_spi_exception_set(PyObject*excclass,ErrorData*edata);
@@ -193,7 +192,7 @@ PLy_spi_execute(PyObject *self, PyObject *args)
193192
returnNULL;
194193
}
195194

196-
staticPyObject*
195+
PyObject*
197196
PLy_spi_execute_plan(PyObject*ob,PyObject*list,longlimit)
198197
{
199198
volatileintnargs;

‎src/pl/plpython/plpy_spi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
externPyObject*PLy_spi_prepare(PyObject*self,PyObject*args);
1212
externPyObject*PLy_spi_execute(PyObject*self,PyObject*args);
13+
externPyObject*PLy_spi_execute_plan(PyObject*ob,PyObject*list,longlimit);
1314

1415
typedefstructPLyExceptionEntry
1516
{

‎src/pl/plpython/sql/plpython_spi.sql

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ return None
3737
'
3838
LANGUAGE plpythonu;
3939

40+
CREATEFUNCTIONspi_prepared_plan_test_two(atext) RETURNStext
41+
AS
42+
'if "myplan" not in SD:
43+
q = "SELECT count(*) FROM users WHERE lname = $1"
44+
SD["myplan"] = plpy.prepare(q, [ "text" ])
45+
try:
46+
rv = SD["myplan"].execute([a])
47+
return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
48+
except Exception, ex:
49+
plpy.error(str(ex))
50+
return None
51+
'
52+
LANGUAGE plpythonu;
53+
4054
CREATEFUNCTIONspi_prepared_plan_test_nested(atext) RETURNStext
4155
AS
4256
'if "myplan" not in SD:
@@ -79,7 +93,7 @@ return a + r
7993
--
8094
select nested_call_one('pass this along');
8195
select spi_prepared_plan_test_one('doe');
82-
selectspi_prepared_plan_test_one('smith');
96+
selectspi_prepared_plan_test_two('smith');
8397
select spi_prepared_plan_test_nested('smith');
8498

8599
SELECT join_sequences(sequences)FROM sequences;
@@ -275,7 +289,7 @@ plan = plpy.prepare(
275289
["text"])
276290
for rowinplpy.cursor(plan, ["w"]):
277291
yield row['fname']
278-
for rowinplpy.cursor(plan,["j"]):
292+
for rowinplan.cursor(["j"]):
279293
yield row['fname']
280294
$$ LANGUAGE plpythonu;
281295

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp