Commit 206bec11 authored by Peter Eisentraut's avatar Peter Eisentraut

Improve PL/Python database access function documentation

Organize the function descriptions as a list instead of running text,
for easier access.
parent dcb33b1c
...@@ -877,134 +877,169 @@ $$ LANGUAGE plpythonu; ...@@ -877,134 +877,169 @@ $$ LANGUAGE plpythonu;
<title>Database Access Functions</title> <title>Database Access Functions</title>
<para> <para>
The <literal>plpy</literal> module provides two The <literal>plpy</literal> module provides several functions to execute
functions called <function>execute</function> and database commands:
<function>prepare</function>. Calling
<function>plpy.execute</function> with a query string and an
optional limit argument causes that query to be run and the result
to be returned in a result object. The result object emulates a
list or dictionary object. The result object can be accessed by
row number and column name. It has these additional methods:
<function>nrows</function> which returns the number of rows
returned by the query, <function>status</function> which is the
<function>SPI_execute()</function> return value,
<function>colnames</function> which is the list of column names,
<function>coltypes</function> which is the list of column type OIDs,
and <function>coltypmods</function> which is the list of type-specific type
modifiers for the columns. The result object can be modified.
</para> </para>
<para> <variablelist>
Note that calling <literal>plpy.execute</literal> will cause the entire <varlistentry>
result set to be read into memory. Only use that function when you are sure <term><literal>plpy.<function>execute</function>(<replaceable>query</replaceable> [, <replaceable>max-rows</replaceable>])</literal></term>
that the result set will be relatively small. If you don't want to risk <listitem>
excessive memory usage when fetching large results, <para>
use <literal>plpy.cursor</literal> rather Calling <function>plpy.execute</function> with a query string and an
than <literal>plpy.execute</literal>. optional row limit argument causes that query to be run and the result to
</para> be returned in a result object.
</para>
<para> <para>
For example: The result object emulates a list or dictionary object. The result
object can be accessed by row number and column name. For example:
<programlisting> <programlisting>
rv = plpy.execute("SELECT * FROM my_table", 5) rv = plpy.execute("SELECT * FROM my_table", 5)
</programlisting> </programlisting>
returns up to 5 rows from <literal>my_table</literal>. If returns up to 5 rows from <literal>my_table</literal>. If
<literal>my_table</literal> has a column <literal>my_table</literal> has a column
<literal>my_column</literal>, it would be accessed as: <literal>my_column</literal>, it would be accessed as:
<programlisting> <programlisting>
foo = rv[i]["my_column"] foo = rv[i]["my_column"]
</programlisting> </programlisting>
</para> </para>
<para> <para>
<indexterm><primary>preparing a query</><secondary>in PL/Python</></indexterm> The result object has these additional methods:
The second function, <function>plpy.prepare</function>, prepares <variablelist>
the execution plan for a query. It is called with a query string <varlistentry>
and a list of parameter types, if you have parameter references in <term><literal><function>nrows</function>()</literal></term>
the query. For example: <listitem>
<para>
Returns the number of rows returned or processed by the query.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal><function>status</function>()</literal></term>
<listitem>
<para>
The <function>SPI_execute()</function> return value.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal><function>colnames</function>()</literal></term>
<term><literal><function>coltypes</function>()</literal></term>
<term><literal><function>coltypmods</function>()</literal></term>
<listitem>
<para>
Return a list of column names, list of column type OIDs, and list of
type-specific type modifiers for the columns, respectively.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The result object can be modified.
</para>
<para>
Note that calling <literal>plpy.execute</literal> will cause the entire
result set to be read into memory. Only use that function when you are
sure that the result set will be relatively small. If you don't want to
risk excessive memory usage when fetching large results,
use <literal>plpy.cursor</literal> rather
than <literal>plpy.execute</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>plpy.<function>prepare</function>(<replaceable>query</replaceable> [, <replaceable>argtypes</replaceable>])</literal></term>
<term><literal>plpy.<function>execute</function>(<replaceable>plan</replaceable> [, <replaceable>arguments</replaceable> [, <replaceable>max-rows</replaceable>]])</literal></term>
<listitem>
<para>
<indexterm><primary>preparing a query</><secondary>in PL/Python</></indexterm>
<function>plpy.prepare</function> prepares the execution plan for a
query. It is called with a query string and a list of parameter types,
if you have parameter references in the query. For example:
<programlisting> <programlisting>
plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ]) plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", ["text"])
</programlisting> </programlisting>
<literal>text</literal> is the type of the variable you will be <literal>text</literal> is the type of the variable you will be passing
passing for <literal>$1</literal>. After preparing a statement, you for <literal>$1</literal>. The second argument is optional if you don't
use the function <function>plpy.execute</function> to run it: want to pass any parameters to the query.
</para>
<para>
After preparing a statement, you use a variant of the
function <function>plpy.execute</function> to run it:
<programlisting> <programlisting>
rv = plpy.execute(plan, [ "name" ], 5) rv = plpy.execute(plan, ["name"], 5)
</programlisting> </programlisting>
The third argument is the limit and is optional. Pass the plan as the first argument (instead of the query string), and a
</para> list of values to substitute into the query as the second argument. The
second argument is optional if the query does not expect any parameters.
The third argument is the optional row limit as before.
</para>
<para> <para>
Query parameters and result row fields are converted between Query parameters and result row fields are converted between PostgreSQL
PostgreSQL and Python data types as described and Python data types as described in <xref linkend="plpython-data">.
in <xref linkend="plpython-data">. The exception is that composite The exception is that composite types are currently not supported: They
types are currently not supported: They will be rejected as query will be rejected as query parameters and are converted to strings when
parameters and are converted to strings when appearing in a query appearing in a query result. As a workaround for the latter problem, the
result. As a workaround for the latter problem, the query can query can sometimes be rewritten so that the composite type result
sometimes be rewritten so that the composite type result appears as appears as a result row rather than as a field of the result row.
a result row rather than as a field of the result row. Alternatively, the resulting string could be parsed apart by hand, but
Alternatively, the resulting string could be parsed apart by hand, this approach is not recommended because it is not future-proof.
but this approach is not recommended because it is not </para>
future-proof.
</para>
<para> <para>
When you prepare a plan using the PL/Python module it is When you prepare a plan using the PL/Python module it is automatically
automatically saved. Read the SPI documentation (<xref saved. Read the SPI documentation (<xref linkend="spi">) for a
linkend="spi">) for a description of what this means. description of what this means. In order to make effective use of this
In order to make effective use of this across function calls across function calls one needs to use one of the persistent storage
one needs to use one of the persistent storage dictionaries dictionaries <literal>SD</literal> or <literal>GD</literal> (see
<literal>SD</literal> or <literal>GD</literal> (see <xref linkend="plpython-sharing">). For example:
<xref linkend="plpython-sharing">). For example:
<programlisting> <programlisting>
CREATE FUNCTION usesavedplan() RETURNS trigger AS $$ CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
plan = SD.setdefault("plan", plpy.prepare("SELECT 1")) plan = SD.setdefault("plan", plpy.prepare("SELECT 1"))
# rest of function # rest of function
$$ LANGUAGE plpythonu; $$ LANGUAGE plpythonu;
</programlisting> </programlisting>
</para> </para>
</listitem>
</sect2> </varlistentry>
<sect2>
<title>Accessing Data with Cursors</title>
<para>
The <literal>plpy.cursor</literal> function accepts the same arguments
as <literal>plpy.execute</literal> (except for <literal>limit</literal>)
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. The
cursor object provides a <literal>fetch</literal> method that accepts an
integer parameter and returns a result object. Each time you
call <literal>fetch</literal>, the returned object will contain the next
batch of rows, never larger than the parameter value. Once all rows are
exhausted, <literal>fetch</literal> starts returning an empty result
object. Cursor objects also provide an
<ulink url="http://docs.python.org/library/stdtypes.html#iterator-types">iterator
interface</ulink>, yielding one row at a time until all rows are exhausted.
Data fetched that way is not returned as result objects, but rather as
dictionaries, each dictionary corresponding to a single result row.
</para>
<para> <varlistentry>
Cursors are automatically disposed of. But if you want to explicitly <term><literal>plpy.<function>cursor</function>(<replaceable>query</replaceable>)</literal></term>
release all resources held by a cursor, use the <literal>close</literal> <term><literal>plpy.<function>cursor</function>(<replaceable>plan</replaceable> [, <replaceable>arguments</replaceable>])</literal></term>
method. Once closed, a cursor cannot be fetched from anymore. <listitem>
</para> <para>
The <literal>plpy.cursor</literal> function accepts the same arguments
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.
</para>
<tip> <para>
<para> The cursor object provides a <literal>fetch</literal> method that accepts
Do not confuse objects created by <literal>plpy.cursor</literal> with an integer parameter and returns a result object. Each time you
DB-API cursors as defined by call <literal>fetch</literal>, the returned object will contain the next
the <ulink url="http://www.python.org/dev/peps/pep-0249/">Python Database batch of rows, never larger than the parameter value. Once all rows are
API specification</ulink>. They don't have anything in common except for exhausted, <literal>fetch</literal> starts returning an empty result
the name. object. Cursor objects also provide an
</para> <ulink url="http://docs.python.org/library/stdtypes.html#iterator-types">iterator
</tip> interface</ulink>, yielding one row at a time until all rows are
exhausted. Data fetched that way is not returned as result objects, but
rather as dictionaries, each dictionary corresponding to a single result
row.
</para>
<para> <para>
An example of two ways of processing data from a large table is: An example of two ways of processing data from a large table is:
<programlisting> <programlisting>
CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$ CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$
odd = 0 odd = 0
...@@ -1035,7 +1070,27 @@ rows = list(plpy.cursor(plan, [2])) ...@@ -1035,7 +1070,27 @@ rows = list(plpy.cursor(plan, [2]))
return len(rows) return len(rows)
$$ LANGUAGE plpythonu; $$ LANGUAGE plpythonu;
</programlisting> </programlisting>
</para> </para>
<para>
Cursors are automatically disposed of. But if you want to explicitly
release all resources held by a cursor, use the <literal>close</literal>
method. Once closed, a cursor cannot be fetched from anymore.
</para>
<tip>
<para>
Do not confuse objects created by <literal>plpy.cursor</literal> with
DB-API cursors as defined by
the <ulink url="http://www.python.org/dev/peps/pep-0249/">Python
Database API specification</ulink>. They don't have anything in common
except for the name.
</para>
</tip>
</listitem>
</varlistentry>
</variablelist>
</sect2> </sect2>
<sect2 id="plpython-trapping"> <sect2 id="plpython-trapping">
......
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