<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),