@ -2812,22 +2812,50 @@ HeapTupleGetDatum(HeapTuple tuple)
<title>Returning Sets</title>
<title>Returning Sets</title>
<para>
<para>
There is also a special API that provides support for returning
C-language functions have two options for returning sets (multiple
sets (multiple rows) from a C-language function. A set-returning
rows). In one method, called <firstterm>ValuePerCall</firstterm>
function must follow the version-1 calling conventions. Also,
mode, a set-returning function is called repeatedly (passing the same
source files must include <filename>funcapi.h</filename>, as
arguments each time) and it returns one new row on each call, until
above.
it has no more rows to return and signals that by returning NULL.
</para>
The set-returning function (<acronym>SRF</acronym>) must therefore
save enough state across calls to remember what it was doing and
<para>
return the correct next item on each call.
A set-returning function (<acronym>SRF</acronym>) is called
In the other method, called <firstterm>Materialize</firstterm> mode,
once for each item it returns. The <acronym>SRF</acronym> must
a SRF fills and returns a tuplestore object containing its
therefore save enough state to remember what it was doing and
entire result; then only one call occurs for the whole result, and
return the next item on each call.
no inter-call state is needed.
The structure <structname>FuncCallContext</structname> is provided to help
</para>
control this process. Within a function, <literal>fcinfo->flinfo->fn_extra</literal>
is used to hold a pointer to <structname>FuncCallContext</structname>
<para>
across calls.
When using ValuePerCall mode, it is important to remember that the
query is not guaranteed to be run to completion; that is, due to
options such as <literal>LIMIT</literal>, the executor might stop
making calls to the set-returning function before all rows have been
fetched. This means it is not safe to perform cleanup activities in
the last call, because that might not ever happen. It's recommended
to use Materialize mode for functions that need access to external
resources, such as file descriptors.
</para>
<para>
The remainder of this section documents a set of helper macros that
are commonly used (though not required to be used) for SRFs using
ValuePerCall mode. Additional details about Materialize mode can be
found in <filename>src/backend/utils/fmgr/README</filename>. Also,
the <filename>contrib</filename> modules in
the <productname>PostgreSQL</productname> source distribution contain
many examples of SRFs using both ValuePerCall and Materialize mode.
</para>
<para>
To use the ValuePerCall support macros described here,
include <filename>funcapi.h</filename>. These macros work with a
structure <structname>FuncCallContext</structname> that contains the
state that needs to be saved across calls. Within the calling
SRF, <literal>fcinfo->flinfo->fn_extra</literal> is used to
hold a pointer to <structname>FuncCallContext</structname> across
calls. The macros automatically fill that field on first use,
and expect to find the same pointer there on subsequent uses.
<programlisting>
<programlisting>
typedef struct FuncCallContext
typedef struct FuncCallContext
{
{
@ -2892,29 +2920,26 @@ typedef struct FuncCallContext
</para>
</para>
<para>
<para>
An <acronym>SRF</acronym> uses several functions and macros that
The macros to be used by an <acronym>SRF</acronym> using this
automatically manipulate the <structname>FuncCallContext</structname>
infrastructure are:
structure (and expect to find it via <literal>fn_extra</literal>). Use:
<programlisting>
<programlisting>
SRF_IS_FIRSTCALL()
SRF_IS_FIRSTCALL()
</programlisting>
</programlisting>
to determine if your function is being called for the first or a
Use this to determine if your function is being called for the first or a
subsequent time. On the first call (only) use :
subsequent time. On the first call (only), call :
<programlisting>
<programlisting>
SRF_FIRSTCALL_INIT()
SRF_FIRSTCALL_INIT()
</programlisting>
</programlisting>
to initialize the <structname>FuncCallContext</structname>. On every function call,
to initialize the <structname>FuncCallContext</structname>. On every function call,
including the first, use :
including the first, call :
<programlisting>
<programlisting>
SRF_PERCALL_SETUP()
SRF_PERCALL_SETUP()
</programlisting>
</programlisting>
to properly set up for using the <structname>FuncCallContext</structname>
to set up for using the <structname>FuncCallContext</structname>.
and clearing any previously returned data left over from the
previous pass.
</para>
</para>
<para>
<para>
If your function has data to return, use:
If your function has data to return in the current call , use:
<programlisting>
<programlisting>
SRF_RETURN_NEXT(funcctx, result)
SRF_RETURN_NEXT(funcctx, result)
</programlisting>
</programlisting>
@ -2938,7 +2963,14 @@ SRF_RETURN_DONE(funcctx)
<structfield>multi_call_memory_ctx</structfield> is a suitable location for any
<structfield>multi_call_memory_ctx</structfield> is a suitable location for any
data that needs to survive until the <acronym>SRF</acronym> is finished running. In most
data that needs to survive until the <acronym>SRF</acronym> is finished running. In most
cases, this means that you should switch into
cases, this means that you should switch into
<structfield>multi_call_memory_ctx</structfield> while doing the first-call setup.
<structfield>multi_call_memory_ctx</structfield> while doing the
first-call setup.
Use <literal>funcctx->user_fctx</literal> to hold a pointer to
any such cross-call data structures.
(Data you allocate
in <structfield>multi_call_memory_ctx</structfield> will go away
automatically when the query ends, so it is not necessary to free
that data manually, either.)
</para>
</para>
<warning>
<warning>
@ -2995,8 +3027,8 @@ my_set_returning_function(PG_FUNCTION_ARGS)
}
}
else
else
{
{
/* Here we are done returning items and just need to clean up: */
/* Here we are done returning items, so just report that fact. */
<replaceable>user code</replaceable>
/* (Resist the temptation to put cleanup code here.) */
SRF_RETURN_DONE(funcctx);
SRF_RETURN_DONE(funcctx);
}
}
}
}
@ -3118,12 +3150,6 @@ CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,
Notice that in this method the output type of the function is formally
Notice that in this method the output type of the function is formally
an anonymous <structname>record</structname> type.
an anonymous <structname>record</structname> type.
</para>
</para>
<para>
The directory <link linkend="tablefunc"><filename>contrib/tablefunc</filename></link>
module in the source distribution contains more examples of
set-returning functions.
</para>
</sect2>
</sect2>
<sect2>
<sect2>