Home Explore Blog CI



postgresql

30th chunk of `doc/src/sgml/xfunc.sgml`
ef2de2a347f03e63f06a1807f3a3b754388e6dfe118ea3120000000100000fa0
 <type>Datum</type>.
     Note that neither arguments nor result are allowed to be NULL when
     using these convenience functions.
    </para>

    <para>
     For example, to call the <function>starts_with(text, text)</function>
     function from C, you can search through the catalog and find out that
     its C implementation is the
     <function>Datum text_starts_with(PG_FUNCTION_ARGS)</function>
     function.  Typically you would
     use <literal>DirectFunctionCall2(text_starts_with, ...)</literal> to
     call such a function.  However, <function>starts_with(text,
     text)</function> requires collation information, so it will fail
     with <quote>could not determine which collation to use for string
     comparison</quote> if called that way.  Instead you must
     use <literal>DirectFunctionCall2Coll(text_starts_with, ...)</literal>
     and provide the desired collation, which typically is just passed
     through from <function>PG_GET_COLLATION()</function>, as shown in the
     example below.
    </para>

    <para>
     <filename>fmgr.h</filename> also supplies macros that facilitate
     conversions between C types and <type>Datum</type>.  For example to
     turn <type>Datum</type> into <type>text*</type>, you can
     use <function>DatumGetTextPP(X)</function>.  While some types have macros
     named like <function>TypeGetDatum(X)</function> for the reverse
     conversion, <type>text*</type> does not; it's sufficient to use the
     generic macro <function>PointerGetDatum(X)</function> for that.
     If your extension defines additional types, it is usually convenient to
     define similar macros for your types too.
    </para>

    <para>
     Here are some examples using the version-1 calling convention:
    </para>

<programlisting><![CDATA[
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#include "varatt.h"

PG_MODULE_MAGIC;

/* by value */

PG_FUNCTION_INFO_V1(add_one);

Datum
add_one(PG_FUNCTION_ARGS)
{
    int32   arg = PG_GETARG_INT32(0);

    PG_RETURN_INT32(arg + 1);
}

/* by reference, fixed length */

PG_FUNCTION_INFO_V1(add_one_float8);

Datum
add_one_float8(PG_FUNCTION_ARGS)
{
    /* The macros for FLOAT8 hide its pass-by-reference nature. */
    float8   arg = PG_GETARG_FLOAT8(0);

    PG_RETURN_FLOAT8(arg + 1.0);
}

PG_FUNCTION_INFO_V1(makepoint);

Datum
makepoint(PG_FUNCTION_ARGS)
{
    /* Here, the pass-by-reference nature of Point is not hidden. */
    Point     *pointx = PG_GETARG_POINT_P(0);
    Point     *pointy = PG_GETARG_POINT_P(1);
    Point     *new_point = (Point *) palloc(sizeof(Point));

    new_point->x = pointx->x;
    new_point->y = pointy->y;

    PG_RETURN_POINT_P(new_point);
}

/* by reference, variable length */

PG_FUNCTION_INFO_V1(copytext);

Datum
copytext(PG_FUNCTION_ARGS)
{
    text     *t = PG_GETARG_TEXT_PP(0);

    /*
     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the
     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a
     * full-length header.
     */
    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);
    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);

    /*
     * VARDATA is a pointer to the data region of the new struct.  The source
     * could be a short datum, so retrieve its data through VARDATA_ANY.
     */
    memcpy(VARDATA(new_t),          /* destination */
           VARDATA_ANY(t),          /* source */
           VARSIZE_ANY_EXHDR(t));   /* how many bytes */
    PG_RETURN_TEXT_P(new_t);
}

PG_FUNCTION_INFO_V1(concat_text);

Datum
concat_text(PG_FUNCTION_ARGS)
{
    text  *arg1 = PG_GETARG_TEXT_PP(0);
    text  *arg2 = PG_GETARG_TEXT_PP(1);
    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);
    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);
    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;
    text *new_text = (text *) palloc(new_text_size);

    SET_VARSIZE(new_text, new_text_size);
    memcpy(VARDATA(new_text), VARDATA_ANY(arg1),

Title: Version 1 Calling Conventions: Examples and Datum Conversion Macros
Summary
This section provides examples of using the version-1 calling convention in PostgreSQL C functions, including functions that handle data by value, fixed-length references (like `float8`), and variable-length references (like `text`). It emphasizes the importance of using the correct `DirectFunctionCall` variant (e.g., `DirectFunctionCall2Coll`) when dealing with collation-aware functions like `starts_with`. The section also covers macros available in `fmgr.h` for converting between C types and the `Datum` type, such as `DatumGetTextPP(X)` for converting `Datum` to `text*` and `PointerGetDatum(X)` for the reverse conversion. Several example functions (`add_one`, `add_one_float8`, `makepoint`, `copytext`, `concat_text`) are provided to illustrate practical implementations.