<acronym>SRF</acronym> is finished running. In most
cases, this means that you should switch into
<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>
<warning>
<para>
While the actual arguments to the function remain unchanged between
calls, if you detoast the argument values (which is normally done
transparently by the
<function>PG_GETARG_<replaceable>xxx</replaceable></function> macro)
in the transient context then the detoasted copies will be freed on
each cycle. Accordingly, if you keep references to such values in
your <structfield>user_fctx</structfield>, you must either copy them into the
<structfield>multi_call_memory_ctx</structfield> after detoasting, or ensure
that you detoast the values only in that context.
</para>
</warning>
<para>
A complete pseudo-code example looks like the following:
<programlisting>
Datum
my_set_returning_function(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
Datum result;
<replaceable>further declarations as needed</replaceable>
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* One-time setup code appears here: */
<replaceable>user code</replaceable>
<replaceable>if returning composite</replaceable>
<replaceable>build TupleDesc, and perhaps AttInMetadata</replaceable>
<replaceable>endif returning composite</replaceable>
<replaceable>user code</replaceable>
MemoryContextSwitchTo(oldcontext);
}
/* Each-time setup code appears here: */
<replaceable>user code</replaceable>
funcctx = SRF_PERCALL_SETUP();
<replaceable>user code</replaceable>
/* this is just one way we might test whether we are done: */
if (funcctx->call_cntr < funcctx->max_calls)
{
/* Here we want to return another item: */
<replaceable>user code</replaceable>
<replaceable>obtain result Datum</replaceable>
SRF_RETURN_NEXT(funcctx, result);
}
else
{
/* Here we are done returning items, so just report that fact. */
/* (Resist the temptation to put cleanup code here.) */
SRF_RETURN_DONE(funcctx);
}
}
</programlisting>
</para>
<para>
A complete example of a simple <acronym>SRF</acronym> returning a composite type
looks like:
<programlisting><![CDATA[
PG_FUNCTION_INFO_V1(retcomposite);
Datum
retcomposite(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tupdesc;
AttInMetadata *attinmeta;
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* total number of tuples to be returned */
funcctx->max_calls = PG_GETARG_INT32(0);
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));