achieved by ending the procedure without a <literal>return</literal>
statement or by using a <literal>return</literal> statement without
argument); otherwise, an error will be raised.
</para>
<para>
For example, a function to return the greater of two integers can be
defined as:
<programlisting>
CREATE FUNCTION pymax (a integer, b integer)
RETURNS integer
AS $$
if a > b:
return a
return b
$$ LANGUAGE plpython3u;
</programlisting>
The Python code that is given as the body of the function definition
is transformed into a Python function. For example, the above results in:
<programlisting>
def __plpython_procedure_pymax_23456():
if a > b:
return a
return b
</programlisting>
assuming that 23456 is the OID assigned to the function by
<productname>PostgreSQL</productname>.
</para>
<para>
The arguments are set as global variables. Because of the scoping
rules of Python, this has the subtle consequence that an argument
variable cannot be reassigned inside the function to the value of
an expression that involves the variable name itself, unless the
variable is redeclared as global in the block. For example, the
following won't work:
<programlisting>
CREATE FUNCTION pystrip(x text)
RETURNS text
AS $$
x = x.strip() # error
return x
$$ LANGUAGE plpython3u;
</programlisting>
because assigning to <varname>x</varname>
makes <varname>x</varname> a local variable for the entire block,
and so the <varname>x</varname> on the right-hand side of the
assignment refers to a not-yet-assigned local
variable <varname>x</varname>, not the PL/Python function
parameter. Using the <literal>global</literal> statement, this can
be made to work:
<programlisting>
CREATE FUNCTION pystrip(x text)
RETURNS text
AS $$
global x
x = x.strip() # ok now
return x
$$ LANGUAGE plpython3u;
</programlisting>
But it is advisable not to rely on this implementation detail of
PL/Python. It is better to treat the function parameters as
read-only.
</para>
</sect1>
<sect1 id="plpython-data">
<title>Data Values</title>
<para>
Generally speaking, the aim of PL/Python is to provide
a <quote>natural</quote> mapping between the PostgreSQL and the
Python worlds. This informs the data mapping rules described
below.
</para>
<sect2 id="plpython-data-type-mapping">
<title>Data Type Mapping</title>
<para>
When a PL/Python function is called, its arguments are converted from
their PostgreSQL data type to a corresponding Python type:
<itemizedlist>
<listitem>
<para>
PostgreSQL <type>boolean</type> is converted to Python <type>bool</type>.
</para>
</listitem>
<listitem>
<para>
PostgreSQL <type>smallint</type>, <type>int</type>, <type>bigint</type>
and <type>oid</type> are converted to Python <type>int</type>.
</para>
</listitem>
<listitem>
<para>
PostgreSQL <type>real</type> and <type>double</type> are converted to
Python <type>float</type>.
</para>
</listitem>
<listitem>
<para>
PostgreSQL <type>numeric</type> is converted to
Python <type>Decimal</type>. This type is imported from
the <literal>cdecimal</literal> package if that is available.
Otherwise,
<literal>decimal.Decimal</literal> from the standard library will be
used. <literal>cdecimal</literal> is significantly faster
than <literal>decimal</literal>. In Python 3.3 and up,
however, <literal>cdecimal</literal> has been integrated into the
standard library under the name <literal>decimal</literal>, so there is
no longer any difference.
</para>
</listitem>
<listitem>
<para>
PostgreSQL <type>bytea</type> is converted to Python <type>bytes</type>.
</para>
</listitem>
<listitem>
<para>
All other data types, including the PostgreSQL