| The PostgreSQL 9.0 Reference Manual - Volume 2 - Programming Guide
by The PostgreSQL Global Development Group Paperback (6"x9"), 478 pages ISBN 9781906966065 RRP £14.95 ($19.95) Sales of this book support the PostgreSQL project! Get a printed copy>>> |
5.9.4 Version 1 Calling Conventions
The version-1 calling convention relies on macros to suppress most of the complexity of passing arguments and results. The C declaration of a version-1 function is always:
Datum funcname(PG_FUNCTION_ARGS)
In addition, the macro call:
PG_FUNCTION_INFO_V1(funcname);
must appear in the same source file. (Conventionally, it's
written just before the function itself.) This macro call is not
needed for internal-language functions, since
PostgreSQL assumes that all internal functions
use the version-1 convention. It is, however, required for
dynamically-loaded functions.
In a version-1 function, each actual argument is fetched using a
PG_GETARG_xxx()
macro that corresponds to the argument's data type, and the
result is returned using a
PG_RETURN_xxx()
macro for the return type.
PG_GETARG_xxx()
takes as its argument the number of the function argument to
fetch, where the count starts at 0.
PG_RETURN_xxx()
takes as its argument the actual value to return.
Here we show the same functions as above, coded in version-1 style:
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
/* 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_P(0);
/* VARSIZE is the total size of the struct in bytes. */
text *new_t = (text *) palloc(VARSIZE(t));
SET_VARSIZE(new_t, VARSIZE(t));
/* VARDATA is a pointer to the data region of the struct. */
memcpy((void *) VARDATA(new_t), /* destination */
(void *) VARDATA(t), /* source */
VARSIZE(t) - VARHDRSZ); /* 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_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int32 new_text_size =
VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
text *new_text = (text *) palloc(new_text_size);
SET_VARSIZE(new_text, new_text_size);
memcpy(VARDATA(new_text), VARDATA(arg1),
VARSIZE(arg1) - VARHDRSZ);
memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ),
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
PG_RETURN_TEXT_P(new_text);
}
The CREATE FUNCTION commands are the same as
for the version-0 equivalents.
At first glance, the version-1 coding conventions might appear to
be just pointless obscurantism. They do, however, offer a number
of improvements, because the macros can hide unnecessary detail.
An example is that in coding add_one_float8, we no longer need to
be aware that float8 is a pass-by-reference type. Another
example is that the GETARG macros for variable-length types allow
for more efficient fetching of “toasted” (compressed or
out-of-line) values.
One big improvement in version-1 functions is better handling of null
inputs and results. The macro PG_ARGISNULL(n)
allows a function to test whether each input is null. (Of course, doing
this is only necessary in functions not declared “strict”.)
As with the
PG_GETARG_xxx() macros,
the input arguments are counted beginning at zero. Note that one
should refrain from executing
PG_GETARG_xxx() until
one has verified that the argument isn't null.
To return a null result, execute PG_RETURN_NULL();
this works in both strict and nonstrict functions.
Other options provided in the new-style interface are two
variants of the
PG_GETARG_xxx()
macros. The first of these,
PG_GETARG_xxx_COPY(),
guarantees to return a copy of the specified argument that is
safe for writing into. (The normal macros will sometimes return a
pointer to a value that is physically stored in a table, which
must not be written to. Using the
PG_GETARG_xxx_COPY()
macros guarantees a writable result.)
The second variant consists of the
PG_GETARG_xxx_SLICE()
macros which take three arguments. The first is the number of the
function argument (as above). The second and third are the offset and
length of the segment to be returned. Offsets are counted from
zero, and a negative length requests that the remainder of the
value be returned. These macros provide more efficient access to
parts of large values in the case where they have storage type
“external”. (The storage type of a column can be specified using
ALTER TABLE tablename ALTER
COLUMN colname SET STORAGE
storagetype. storagetype is one of
plain, external, extended,
or main.)
Finally, the version-1 function call conventions make it possible to return set results (section 5.9.10 Returning Sets) and implement trigger functions (section 6 Triggers) and procedural-language call handlers (Writing A Procedural Language Handler). Version-1 code is also more portable than version-0, because it does not break restrictions on function call protocol in the C standard. For more details see ‘src/backend/utils/fmgr/README’ in the source distribution.
| ISBN 9781906966065 | The PostgreSQL 9.0 Reference Manual - Volume 2 - Programming Guide | See the print edition |