Update refcursor documentation with examples of how to return pl/pgsql

refcursors.
This commit is contained in:
Bruce Momjian 2002-04-09 02:31:58 +00:00
parent 308d50cdea
commit 663aabaa6e
1 changed files with 88 additions and 25 deletions

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.54 2002/03/22 19:20:18 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.55 2002/04/09 02:31:58 momjian Exp $
-->
<chapter id="plpgsql">
@ -762,7 +762,7 @@ CREATE FUNCTION logfunc2 (TEXT) RETURNS TIMESTAMP AS '
<para>
If the expression's result data type doesn't match the variable's
data type, or the variable has a specific size/precision
(as for <type>char(20)</type>), the result value will be implicitly
(like <type>char(20)</type>), the result value will be implicitly
converted by the <application>PL/pgSQL</application> interpreter using
the result type's output-function and
the variable type's input-function. Note that this could potentially
@ -880,7 +880,7 @@ PERFORM <replaceable>query</replaceable>;
This executes a <literal>SELECT</literal>
<replaceable>query</replaceable> and discards the
result. <application>PL/pgSQL</application> variables are substituted
into the query as usual.
in the query as usual.
</para>
<note>
@ -927,7 +927,7 @@ EXECUTE <replaceable class="command">query-string</replaceable>;
<para>
Note in particular that no substitution of <application>PL/pgSQL</>
variables is done on the query string. The values of variables must
be inserted into the query string as it is constructed.
be inserted in the query string as it is constructed.
</para>
<para>
@ -1441,16 +1441,16 @@ END LOOP;
<title>Cursors</title>
<para>
Rather than executing a whole query at once, it is possible to
set up a <firstterm>cursor</> that encapsulates the query, and
then read the query result a few rows at a time. One reason
for doing this is to avoid memory overrun when the result contains
a large number of rows. (However, <application>PL/pgSQL</> users
don't normally need to worry about that, since FOR loops automatically
use a cursor internally to avoid memory problems.) A more interesting
possibility is that a function can return a reference to a cursor
that it has set up, allowing the caller to read the rows. This
provides one way of returning a row set from a function.
Rather than executing a whole query at once, it is possible to set
up a <firstterm>cursor</> that encapsulates the query, and then read
the query result a few rows at a time. One reason for doing this is
to avoid memory overrun when the result contains a large number of
rows. (However, <application>PL/pgSQL</> users don't normally need
to worry about that, since FOR loops automatically use a cursor
internally to avoid memory problems.) A more interesting usage is to
return a reference to a cursor that it has created, allowing the
caller to read the rows. This provides one way of returning multiple
rows and columns from a function.
</para>
<sect2 id="plpgsql-cursor-declarations">
@ -1498,11 +1498,10 @@ DECLARE
<para>
Before a cursor can be used to retrieve rows, it must be
<firstterm>opened</>. (This is the equivalent action to
the SQL command <command>DECLARE CURSOR</>.)
<application>PL/pgSQL</> has four forms of the OPEN statement,
two of which are for use with unbound cursor variables
and the other two for use with bound cursor variables.
<firstterm>opened</>. (This is the equivalent action to the SQL
command <command>DECLARE CURSOR</>.) <application>PL/pgSQL</> has
four forms of the OPEN statement, two of which use unbound cursor
variables and the other two use bound cursor variables.
</para>
<sect3>
@ -1518,7 +1517,7 @@ OPEN <replaceable>unbound-cursor</replaceable> FOR SELECT ...;
have been declared as an unbound cursor (that is, as a simple
<type>refcursor</> variable). The SELECT query is treated
in the same way as other SELECTs in <application>PL/pgSQL</>:
<application>PL/pgSQL</> variable names are substituted for,
<application>PL/pgSQL</> variable names are substituted,
and the query plan is cached for possible re-use.
<programlisting>
@ -1539,8 +1538,8 @@ OPEN <replaceable>unbound-cursor</replaceable> FOR EXECUTE <replaceable class="c
to execute. The cursor cannot be open already, and it must
have been declared as an unbound cursor (that is, as a simple
<type>refcursor</> variable). The query is specified as a
string expression in the same way as for the EXECUTE command.
As usual, this gives flexibility for the query to vary
string expression in the same way as in the EXECUTE command.
As usual, this gives flexibility so the query can vary
from one run to the next.
<programlisting>
@ -1562,7 +1561,7 @@ OPEN <replaceable>bound-cursor</replaceable> <optional> ( <replaceable>argument_
The cursor cannot be open already. A list of actual argument
value expressions must appear if and only if the cursor was
declared to take arguments. These values will be substituted
into the query.
in the query.
The query plan for a bound cursor is always considered
cacheable --- there is no equivalent of EXECUTE in this case.
@ -1593,7 +1592,7 @@ OPEN curs3(42);
</para>
<para>
All Portals are implicitly closed at end of transaction. Therefore
All Portals are implicitly closed at transaction end. Therefore
a <type>refcursor</> value is useful to reference an open cursor
only until the end of the transaction.
</para>
@ -1608,7 +1607,7 @@ FETCH <replaceable>cursor</replaceable> INTO <replaceable>target</replaceable>;
FETCH retrieves the next row from the cursor into a target,
which may be a row variable, a record variable, or a comma-separated
list of simple variables, just as for SELECT INTO. As with
list of simple variables, just like SELECT INTO. As with
SELECT INTO, the special variable FOUND may be checked to see
whether a row was obtained or not.
@ -1633,6 +1632,70 @@ CLOSE <replaceable>cursor</replaceable>;
<programlisting>
CLOSE curs1;
</programlisting>
</para>
</sect3>
<sect3>
<title>Returning Cursors</title>
<para>
<application>PL/pgSQL</> functions can return cursors to the
caller. This is used to return multiple rows or columns from the
function. The function opens the cursor and returns the cursor
name to the caller. The caller can then FETCH rows from the
cursor. The cursor can be CLOSEd by the caller, or it will be
closed automatically when the transaction closes.
</para>
<para>
The cursor name returned by the function can be specified by the
caller or automatically generated. The following example shows
how a cursor name can be supplied by the caller:
<programlisting>
CREATE TABLE test (col text);
INSERT INTO test VALUES ('123');
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '
BEGIN
OPEN $1 FOR SELECT col FROM test;
RETURN $1;
END;
' LANGUAGE 'plpgsql';
BEGIN;
SELECT reffunc('funccursor');
FETCH ALL IN funccursor;
COMMIT;
</programlisting>
</para>
<para>
The following example uses automatic cursor name generation:
<programlisting>
CREATE FUNCTION reffunc2() RETURNS refcursor AS '
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT col FROM test;
RETURN ref;
END;
' LANGUAGE 'plpgsql';
BEGIN;
SELECT reffunc2();
reffunc2
--------------------
<unnamed cursor 1>
(1 row)
FETCH ALL IN "<unnamed cursor 1>";
COMMIT;
</programlisting>
</para>
</sect3>