Home Explore Blog CI



postgresql

37th chunk of `doc/src/sgml/xfunc.sgml`
0974da45e5fd7ff5ef9cd82ad96de358b81cd274bf9a558e0000000100000fb3
 "executor/executor.h"  /* for GetAttributeByName() */

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(c_overpaid);

Datum
c_overpaid(PG_FUNCTION_ARGS)
{
    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);
    int32            limit = PG_GETARG_INT32(1);
    bool isnull;
    Datum salary;

    salary = GetAttributeByName(t, "salary", &isnull);
    if (isnull)
        PG_RETURN_BOOL(false);
    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */

    PG_RETURN_BOOL(DatumGetInt32(salary) > limit);
}
]]>
</programlisting>
    </para>

    <para>
     <function>GetAttributeByName</function> is the
     <productname>PostgreSQL</productname> system function that
     returns attributes out of the specified row.  It has
     three arguments: the argument of type <type>HeapTupleHeader</type> passed
     into
     the  function, the name of the desired attribute, and a
     return parameter that tells whether  the  attribute
     is  null.   <function>GetAttributeByName</function> returns a <type>Datum</type>
     value that you can convert to the proper data type by using the
     appropriate <function>DatumGet<replaceable>XXX</replaceable>()</function>
     function.  Note that the return value is meaningless if the null flag is
     set; always check the null flag before trying to do anything with the
     result.
    </para>

    <para>
     There is also <function>GetAttributeByNum</function>, which selects
     the target attribute by column number instead of name.
    </para>

    <para>
     The following command declares the function
     <function>c_overpaid</function> in SQL:

<programlisting>
CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean
    AS '<replaceable>DIRECTORY</replaceable>/funcs', 'c_overpaid'
    LANGUAGE C STRICT;
</programlisting>

     Notice we have used <literal>STRICT</literal> so that we did not have to
     check whether the input arguments were NULL.
    </para>
   </sect2>

   <sect2 id="xfunc-c-returning-rows">
    <title>Returning Rows (Composite Types)</title>

    <para>
     To return a row or composite-type value from a C-language
     function, you can use a special API that provides macros and
     functions to hide most of the complexity of building composite
     data types.  To use this API, the source file must include:
<programlisting>
#include "funcapi.h"
</programlisting>
    </para>

    <para>
     There are two ways you can build a composite data value (henceforth
     a <quote>tuple</quote>): you can build it from an array of Datum values,
     or from an array of C strings that can be passed to the input
     conversion functions of the tuple's column data types.  In either
     case, you first need to obtain or construct a <structname>TupleDesc</structname>
     descriptor for the tuple structure.  When working with Datums, you
     pass the <structname>TupleDesc</structname> to <function>BlessTupleDesc</function>,
     and then call <function>heap_form_tuple</function> for each row.  When working
     with C strings, you pass the <structname>TupleDesc</structname> to
     <function>TupleDescGetAttInMetadata</function>, and then call
     <function>BuildTupleFromCStrings</function> for each row.  In the case of a
     function returning a set of tuples, the setup steps can all be done
     once during the first call of the function.
    </para>

    <para>
     Several helper functions are available for setting up the needed
     <structname>TupleDesc</structname>.  The recommended way to do this in most
     functions returning composite values is to call:
<programlisting>
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
                                   Oid *resultTypeId,
                                   TupleDesc *resultTupleDesc)
</programlisting>
     passing the same <literal>fcinfo</literal> struct passed to the calling function
     itself.  (This of course requires that you use the version-1
     calling conventions.)  <varname>resultTypeId</varname>

Title: Accessing Composite Type Attributes and Returning Rows from C Functions
Summary
The text details how to access attributes within composite types in PostgreSQL using the `GetAttributeByName` and `GetAttributeByNum` functions. It provides an example of creating a C function, `c_overpaid`, that utilizes `GetAttributeByName` and demonstrates the corresponding SQL function declaration. Then, it discusses how to return rows (composite types) from C-language functions using a specialized API. It explains the process of building composite data values (tuples) from Datum values or C strings, emphasizing the importance of obtaining or constructing a `TupleDesc` descriptor. It introduces helper functions like `get_call_result_type` for setting up the necessary `TupleDesc`.