diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index 237c881a5c129331af5ad7feb74273ab313438ce..75a939406c63219b0379d8dc6e27f32d1a274048 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -877,134 +877,169 @@ $$ LANGUAGE plpythonu; <title>Database Access Functions</title> <para> - The <literal>plpy</literal> module provides two - functions called <function>execute</function> and - <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. + The <literal>plpy</literal> module provides several functions to execute + database commands: </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> + <variablelist> + <varlistentry> + <term><literal>plpy.<function>execute</function>(<replaceable>query</replaceable> [, <replaceable>max-rows</replaceable>])</literal></term> + <listitem> + <para> + Calling <function>plpy.execute</function> with a query string and an + optional row limit argument causes that query to be run and the result to + be returned in a result object. + </para> - <para> - For example: + <para> + The result object emulates a list or dictionary object. The result + object can be accessed by row number and column name. For example: <programlisting> rv = plpy.execute("SELECT * FROM my_table", 5) </programlisting> - returns up to 5 rows from <literal>my_table</literal>. If - <literal>my_table</literal> has a column - <literal>my_column</literal>, it would be accessed as: + returns up to 5 rows from <literal>my_table</literal>. If + <literal>my_table</literal> has a column + <literal>my_column</literal>, it would be accessed as: <programlisting> foo = rv[i]["my_column"] </programlisting> - </para> + </para> - <para> - <indexterm><primary>preparing a query</><secondary>in PL/Python</></indexterm> - The second function, <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: + <para> + The result object has these additional methods: + <variablelist> + <varlistentry> + <term><literal><function>nrows</function>()</literal></term> + <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> -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> - <literal>text</literal> is the type of the variable you will be - passing for <literal>$1</literal>. After preparing a statement, you - use the function <function>plpy.execute</function> to run it: + <literal>text</literal> is the type of the variable you will be passing + for <literal>$1</literal>. The second argument is optional if you don't + 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> -rv = plpy.execute(plan, [ "name" ], 5) +rv = plpy.execute(plan, ["name"], 5) </programlisting> - The third argument is the limit and is optional. - </para> + Pass the plan as the first argument (instead of the query string), and a + 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> - Query parameters and result row fields are converted between - PostgreSQL and Python data types as described - in <xref linkend="plpython-data">. The exception is that composite - types are currently not supported: They will be rejected as query - parameters and are converted to strings when appearing in a query - result. As a workaround for the latter problem, the query can - sometimes be rewritten so that the composite type result appears as - a result row rather than as a field of the result row. - Alternatively, the resulting string could be parsed apart by hand, - but this approach is not recommended because it is not - future-proof. - </para> + <para> + Query parameters and result row fields are converted between PostgreSQL + and Python data types as described in <xref linkend="plpython-data">. + The exception is that composite types are currently not supported: They + will be rejected as query parameters and are converted to strings when + appearing in a query result. As a workaround for the latter problem, the + query can sometimes be rewritten so that the composite type result + appears as a result row rather than as a field of the result row. + Alternatively, the resulting string could be parsed apart by hand, but + this approach is not recommended because it is not future-proof. + </para> - <para> - When you prepare a plan using the PL/Python module it is - automatically saved. Read the SPI documentation (<xref - linkend="spi">) for a description of what this means. - In order to make effective use of this across function calls - one needs to use one of the persistent storage dictionaries - <literal>SD</literal> or <literal>GD</literal> (see - <xref linkend="plpython-sharing">). For example: + <para> + When you prepare a plan using the PL/Python module it is automatically + saved. Read the SPI documentation (<xref linkend="spi">) for a + description of what this means. In order to make effective use of this + across function calls one needs to use one of the persistent storage + dictionaries <literal>SD</literal> or <literal>GD</literal> (see + <xref linkend="plpython-sharing">). For example: <programlisting> CREATE FUNCTION usesavedplan() RETURNS trigger AS $$ plan = SD.setdefault("plan", plpy.prepare("SELECT 1")) # rest of function $$ LANGUAGE plpythonu; </programlisting> - </para> - - </sect2> - - <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> + </listitem> + </varlistentry> - <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> + <varlistentry> + <term><literal>plpy.<function>cursor</function>(<replaceable>query</replaceable>)</literal></term> + <term><literal>plpy.<function>cursor</function>(<replaceable>plan</replaceable> [, <replaceable>arguments</replaceable>])</literal></term> + <listitem> + <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> - 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> + <para> + 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> - An example of two ways of processing data from a large table is: + <para> + An example of two ways of processing data from a large table is: <programlisting> CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$ odd = 0 @@ -1035,7 +1070,27 @@ rows = list(plpy.cursor(plan, [2])) return len(rows) $$ LANGUAGE plpythonu; </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 id="plpython-trapping">