Home Explore Blog CI



postgresql

43th chunk of `doc/src/sgml/xfunc.sgml`
a5e1c8d39b25c8ed1f57eef1f1cf86a04a606d532c9042c00000000100000fa2
 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")));

        /*
         * generate attribute metadata needed later to produce tuples from raw
         * C strings
         */
        attinmeta = TupleDescGetAttInMetadata(tupdesc);
        funcctx->attinmeta = attinmeta;

        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    funcctx = SRF_PERCALL_SETUP();

    call_cntr = funcctx->call_cntr;
    max_calls = funcctx->max_calls;
    attinmeta = funcctx->attinmeta;

    if (call_cntr < max_calls)    /* do when there is more left to send */
    {
        char       **values;
        HeapTuple    tuple;
        Datum        result;

        /*
         * Prepare a values array for building the returned tuple.
         * This should be an array of C strings which will
         * be processed later by the type input functions.
         */
        values = (char **) palloc(3 * sizeof(char *));
        values[0] = (char *) palloc(16 * sizeof(char));
        values[1] = (char *) palloc(16 * sizeof(char));
        values[2] = (char *) palloc(16 * sizeof(char));

        snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
        snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
        snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));

        /* build a tuple */
        tuple = BuildTupleFromCStrings(attinmeta, values);

        /* make the tuple into a datum */
        result = HeapTupleGetDatum(tuple);

        /* clean up (this is not really necessary) */
        pfree(values[0]);
        pfree(values[1]);
        pfree(values[2]);
        pfree(values);

        SRF_RETURN_NEXT(funcctx, result);
    }
    else    /* do when there is no more left */
    {
        SRF_RETURN_DONE(funcctx);
    }
}
]]>
</programlisting>

     One way to declare this function in SQL is:
<programlisting>
CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);

CREATE OR REPLACE FUNCTION retcomposite(integer, integer)
    RETURNS SETOF __retcomposite
    AS '<replaceable>filename</replaceable>', 'retcomposite'
    LANGUAGE C IMMUTABLE STRICT;
</programlisting>
     A different way is to use OUT parameters:
<programlisting>
CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,
    OUT f1 integer, OUT f2 integer, OUT f3 integer)
    RETURNS SETOF record
    AS '<replaceable>filename</replaceable>', 'retcomposite'
    LANGUAGE C IMMUTABLE STRICT;
</programlisting>
     Notice that in this method the output type of the function is formally
     an anonymous <structname>record</structname> type.
    </para>
   </sect2>

   <sect2 id="xfunc-c-polymorphic">
    <title>Polymorphic Arguments and Return Types</title>

    <para>
     C-language functions can be declared to accept and
     return the polymorphic types described in <xref
     linkend="extend-types-polymorphic"/>.
     When a function's arguments or return types
     are defined as polymorphic types, the function author cannot know
     in advance what data type it will be called with,

Title: SRF Returning a Composite Type: Example and SQL Declarations
Summary
This section provides a complete C code example of a Set-Returning Function (SRF) that returns a composite type. It details the initialization process during the first call, including memory context setup, tuple descriptor creation, and attribute metadata generation. It also covers the logic for each subsequent call, constructing tuples from C strings and returning them. The section then illustrates two SQL declaration methods for this function: one using a custom composite type and another using OUT parameters to return a set of records. Finally, it introduces the concept of polymorphic arguments and return types for C-language functions.