Home Explore Blog CI



postgresql

42th chunk of `doc/src/sgml/xfunc.sgml`
13776d56bdfc6ba67f0261c9e55febc0a5dbd50451d1ad960000000100000fab
 <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-&gt;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-&gt;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-&gt;call_cntr &lt; funcctx-&gt;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")));

Title: Memory Context Management and SRF Example
Summary
This section emphasizes using the `multi_call_memory_ctx` for storing data across calls in an SRF and advises switching to this context during initial setup. It also warns about detoasting argument values in the transient context and provides a pseudo-code example demonstrating the structure of an SRF, including handling the first call, setting up for each call, returning data, and indicating completion. Lastly, it presents a complete example of an SRF that returns a composite type, illustrating the use of `FuncCallContext`, `TupleDesc`, and `AttInMetadata`.