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

Commit819f22a

Browse files
committed
Allow PL/python to return composite types and result sets
Sven Suursoho
1 parentb1620c5 commit819f22a

File tree

8 files changed

+1359
-99
lines changed

8 files changed

+1359
-99
lines changed

‎doc/src/sgml/plpython.sgml

Lines changed: 287 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.30 2006/05/26 19:23:09 adunstan Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.31 2006/09/02 12:30:01 momjian Exp $ -->
22

33
<chapter id="plpython">
44
<title>PL/Python - Python Procedural Language</title>
@@ -46,28 +46,211 @@
4646
<title>PL/Python Functions</title>
4747

4848
<para>
49-
Functions in PL/Python are declared via theusual <xref
49+
Functions in PL/Python are declared via thestandard <xref
5050
linkend="sql-createfunction" endterm="sql-createfunction-title">
51-
syntax. For example:
51+
syntax:
52+
53+
<programlisting>
54+
CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-list</replaceable>)
55+
RETURNS <replaceable>return-type</replaceable>
56+
AS $$
57+
# PL/Python function body
58+
$$ LANGUAGE plpythonu;
59+
</programlisting>
60+
</para>
61+
62+
<para>
63+
The body of a function is simply a Python script. When the function
64+
is called, all unnamed arguments are passed as elements to the array
65+
<varname>args[]</varname> and named arguments as ordinary variables to the
66+
Python script. The result is returned from the Python code in the usual way,
67+
with <literal>return</literal> or <literal>yield</literal> (in case of
68+
a resultset statement).
69+
</para>
70+
71+
<para>
72+
For example, a function to return the greater of two integers can be
73+
defined as:
74+
5275
<programlisting>
53-
CREATE FUNCTION myfunc(text) RETURNS text
54-
AS 'return args[0]'
55-
LANGUAGE plpythonu;
76+
CREATE FUNCTION pymax (a integer, b integer)
77+
RETURNS integer
78+
AS $$
79+
if a &gt; b:
80+
return a
81+
return b
82+
$$ LANGUAGE plpythonu;
5683
</programlisting>
5784

5885
The Python code that is given as the body of the function definition
59-
gets transformed into a Python function.
60-
For example, the above results in
86+
is transformed into a Python function. For example, the above results in
6187

6288
<programlisting>
63-
def __plpython_procedure_myfunc_23456():
64-
return args[0]
89+
def __plpython_procedure_pymax_23456():
90+
if a &gt; b:
91+
return a
92+
return b
6593
</programlisting>
6694

6795
assuming that 23456 is the OID assigned to the function by
6896
<productname>PostgreSQL</productname>.
6997
</para>
7098

99+
<para>
100+
The <productname>PostgreSQL</> function parameters are available in
101+
the global <varname>args</varname> list. In the
102+
<function>pymax</function> example, <varname>args[0]</varname> contains
103+
whatever was passed in as the first argument and
104+
<varname>args[1]</varname> contains the second argument's value. Alternatively,
105+
one can use named parameters as shown in the example above. This greatly simplifies
106+
the reading and writing of <application>PL/Python</application> code.
107+
</para>
108+
109+
<para>
110+
If an SQL null value<indexterm><primary>null value</primary><secondary
111+
sortas="PL/Python">PL/Python</secondary></indexterm> is passed to a
112+
function, the argument value will appear as <symbol>None</symbol> in
113+
Python. The above function definition will return the wrong answer for null
114+
inputs. We could add <literal>STRICT</literal> to the function definition
115+
to make <productname>PostgreSQL</productname> do something more reasonable:
116+
if a null value is passed, the function will not be called at all,
117+
but will just return a null result automatically. Alternatively,
118+
we could check for null inputs in the function body:
119+
120+
<programlisting>
121+
CREATE FUNCTION pymax (a integer, b integer)
122+
RETURNS integer
123+
AS $$
124+
if (a is None) or (b is None):
125+
return None
126+
if a > b:
127+
return a
128+
return b
129+
$$ LANGUAGE plpythonu;
130+
</programlisting>
131+
132+
As shown above, to return an SQL null value from a PL/Python
133+
function, return the value <symbol>None</symbol>. This can be done whether the
134+
function is strict or not.
135+
</para>
136+
137+
<para>
138+
Composite-type arguments are passed to the function as Python mappings. The
139+
element names of the mapping are the attribute names of the composite type.
140+
If an attribute in the passed row has the null value, it has the value
141+
<symbol>None</symbol> in the mapping. Here is an example:
142+
143+
<programlisting>
144+
CREATE TABLE employee (
145+
name text,
146+
salary integer,
147+
age integer
148+
);
149+
150+
CREATE FUNCTION overpaid (e employee)
151+
RETURNS boolean
152+
AS $$
153+
if e["salary"] &gt; 200000:
154+
return True
155+
if (e["age"] &lt; 30) and (e["salary"] &gt; 100000):
156+
return True
157+
return False
158+
$$ LANGUAGE plpythonu;
159+
</programlisting>
160+
</para>
161+
162+
<para>
163+
There are multiple ways to return row or composite types from a Python
164+
scripts. In following examples we assume to have:
165+
166+
<programlisting>
167+
CREATE TABLE named_value (
168+
name text,
169+
value integer
170+
);
171+
</programlisting>
172+
or
173+
<programlisting>
174+
CREATE TYPE named_value AS (
175+
name text,
176+
value integer
177+
);
178+
</programlisting>
179+
180+
<variablelist>
181+
<varlistentry>
182+
<term>Sequence types (tuple or list), but not <literal>set</literal> (because
183+
it is not indexable)</term>
184+
<listitem>
185+
<para>
186+
Returned sequence objects must have the same number of items as
187+
composite types have fields. Item with index 0 is assigned to the first field
188+
of the composite type, 1 to second and so on. For example:
189+
190+
<programlisting>
191+
CREATE FUNCTION make_pair (name text, value integer)
192+
RETURNS named_value
193+
AS $$
194+
return [ name, value ]
195+
# or alternatively, as tuple: return ( name, value )
196+
$$ LANGUAGE plpythonu;
197+
</programlisting>
198+
199+
To return SQL null in any column, insert <symbol>None</symbol> at
200+
the corresponding position.
201+
</para>
202+
</listitem>
203+
204+
<varlistentry>
205+
<term>Mapping (dictionary)</term>
206+
<listitem>
207+
<para>
208+
Value for a composite type's column is retrieved from the mapping with
209+
the column name as key. Example:
210+
211+
<programlisting>
212+
CREATE FUNCTION make_pair (name text, value integer)
213+
RETURNS named_value
214+
AS $$
215+
return { "name": name, "value": value }
216+
$$ LANGUAGE plpythonu;
217+
</programlisting>
218+
219+
Additional dictionary key/value pairs are ignored. Missing keys are
220+
treated as errors, i.e. to return an SQL null value for any column, insert
221+
<symbol>None</symbol> with the corresponding column name as the key.
222+
</para>
223+
</listitem>
224+
225+
<varlistentry>
226+
<term>Object (any object providing method <literal>__getattr__</literal>)</term>
227+
<listitem>
228+
<para>
229+
Example:
230+
231+
<programlisting>
232+
CREATE FUNCTION make_pair (name text, value integer)
233+
RETURNS named_value
234+
AS $$
235+
class named_value:
236+
def __init__ (self, n, v):
237+
self.name = n
238+
self.value = v
239+
return named_value(name, value)
240+
241+
# or simply
242+
class nv: pass
243+
nv.name = name
244+
nv.value = value
245+
return nv
246+
$$ LANGUAGE plpythonu;
247+
</programlisting>
248+
</para>
249+
</listitem>
250+
</varlistentry>
251+
</variablelist>
252+
</para>
253+
71254
<para>
72255
If you do not provide a return value, Python returns the default
73256
<symbol>None</symbol>. <application>PL/Python</application> translates
@@ -77,13 +260,100 @@ def __plpython_procedure_myfunc_23456():
77260
</para>
78261

79262
<para>
80-
The <productname>PostgreSQL</> function parameters are available in
81-
the global <varname>args</varname> list. In the
82-
<function>myfunc</function> example, <varname>args[0]</> contains
83-
whatever was passed in as the text argument. For
84-
<literal>myfunc2(text, integer)</literal>, <varname>args[0]</>
85-
would contain the <type>text</type> argument and
86-
<varname>args[1]</varname> the <type>integer</type> argument.
263+
A <application>PL/Python</application> function can also return sets of
264+
scalar or composite types. There are serveral ways to achieve this because
265+
the returned object is internally turned into an iterator. For following
266+
examples, let's assume to have composite type:
267+
268+
<programlisting>
269+
CREATE TYPE greeting AS (
270+
how text,
271+
who text
272+
);
273+
</programlisting>
274+
275+
Currently known iterable types are:
276+
<variablelist>
277+
<varlistentry>
278+
<term>Sequence types (tuple, list, set)</term>
279+
<listitem>
280+
<para>
281+
<programlisting>
282+
CREATE FUNCTION greet (how text)
283+
RETURNS SETOF greeting
284+
AS $$
285+
# return tuple containing lists as composite types
286+
# all other combinations work also
287+
return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] )
288+
$$ LANGUAGE plpythonu;
289+
</programlisting>
290+
</para>
291+
</listitem>
292+
</varlistentry>
293+
294+
<varlistentry>
295+
<term>Iterator (any object providing <symbol>__iter__</symbol> and
296+
<symbol>next</symbol> methods)</term>
297+
<listitem>
298+
<para>
299+
<programlisting>
300+
CREATE FUNCTION greet (how text)
301+
RETURNS SETOF greeting
302+
AS $$
303+
class producer:
304+
def __init__ (self, how, who):
305+
self.how = how
306+
self.who = who
307+
self.ndx = -1
308+
309+
def __iter__ (self):
310+
return self
311+
312+
def next (self):
313+
self.ndx += 1
314+
if self.ndx == len(self.who):
315+
raise StopIteration
316+
return ( self.how, self.who[self.ndx] )
317+
318+
return producer(how, [ "World", "PostgreSQL", "PL/Python" ])
319+
$$ LANGUAGE plpythonu;
320+
</programlisting>
321+
</para>
322+
</listitem>
323+
</varlistentry>
324+
325+
<varlistentry>
326+
<term>Generator (<literal>yield</literal>)</term>
327+
<listitem>
328+
<para>
329+
<programlisting>
330+
CREATE FUNCTION greet (how text)
331+
RETURNS SETOF greeting
332+
AS $$
333+
for who in [ "World", "PostgreSQL", "PL/Python" ]:
334+
yield ( how, who )
335+
$$ LANGUAGE plpythonu;
336+
</programlisting>
337+
338+
<warning>
339+
<para>
340+
Currently, due to Python
341+
<ulink url="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1483133&amp;group_id=5470&amp;atid=105470">bug #1483133</ulink>,
342+
some debug versions of Python 2.4
343+
(configured and compiled with option <literal>--with-pydebug</literal>)
344+
are known to crash the <productname>PostgreSQL</productname> server.
345+
Unpatched versions of Fedora 4 contain this bug.
346+
It does not happen in production version of Python or on patched
347+
versions of Fedora 4.
348+
</para>
349+
</warning>
350+
</para>
351+
</listitem>
352+
</varlistentry>
353+
</variablelist>
354+
355+
Whenever new iterable types are added to Python language,
356+
<application>PL/Python</application> is ready to use it.
87357
</para>
88358

89359
<para>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp