- publishing free software manuals
PostgreSQL Reference Manual - Volume 2 - Programming Guide
by The PostgreSQL Global Development Group
Paperback (6"x9"), 408 pages
ISBN 0954612035
RRP £19.95 ($34.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"

/* 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));
  VARATT_SIZEP(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);

  VARATT_SIZEP(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 may 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 ( Volume 4: 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 0954612035PostgreSQL Reference Manual - Volume 2 - Programming GuideSee the print edition