- publishing free software manuals
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.11 Polymorphic Arguments and Return Types

C-language functions can be declared to accept and return the polymorphic types anyelement, anyarray, anynonarray, and anyenum. See section 5.2.5 Polymorphic Types for a more detailed explanation of polymorphic functions. When function arguments or return types are defined as polymorphic types, the function author cannot know in advance what data type it will be called with, or need to return. There are two routines provided in ‘fmgr.h’ to allow a version-1 C function to discover the actual data types of its arguments and the type it is expected to return. The routines are called get_fn_expr_rettype(FmgrInfo *flinfo) and get_fn_expr_argtype(FmgrInfo *flinfo, int argnum). They return the result or argument type OID, or InvalidOid if the information is not available. The structure flinfo is normally accessed as fcinfo->flinfo. The parameter argnum is zero based. get_call_result_type can also be used as an alternative to get_fn_expr_rettype.

For example, suppose we want to write a function to accept a single element of any type, and return a one-dimensional array of that type:

PG_FUNCTION_INFO_V1(make_array);
Datum
make_array(PG_FUNCTION_ARGS)
{
  ArrayType *result;
  Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
  Datum element;
  bool isnull;
  int16 typlen;
  bool typbyval;
  char typalign;
  int ndims;
  int dims[MAXDIM];
  int lbs[MAXDIM];

  if (!OidIsValid(element_type))
    elog(ERROR, "could not determine data type of input");

  /* get the provided element, being careful in case it's
     NULL */
  isnull = PG_ARGISNULL(0);
  if (isnull)
    element = (Datum) 0;
  else
    element = PG_GETARG_DATUM(0);

  /* we have one dimension */
  ndims = 1;
  /* and one element */
  dims[0] = 1;
  /* and lower bound is 1 */
  lbs[0] = 1;

  /* get required info about the element type */
  get_typlenbyvalalign(element_type, &typlen, &typbyval,
                       &typalign);

  /* now build the array */
  result =
      construct_md_array(&element, &isnull, ndims, dims,
                         lbs, element_type, typlen,
                         typbyval, typalign);

  PG_RETURN_ARRAYTYPE_P(result);
}

The following command declares the function make_array in SQL:

CREATE FUNCTION make_array(anyelement) RETURNS anyarray
    AS 'DIRECTORY/funcs', 'make_array'
    LANGUAGE C IMMUTABLE;

There is a variant of polymorphism that is only available to C-language functions: they can be declared to take parameters of type "any". (Note that this type name must be double-quoted, since it's also a SQL reserved word.) This works like anyelement except that it does not constrain different "any" arguments to be the same type, nor do they help determine the function's result type. A C-language function can also declare its final parameter to be VARIADIC "any". This will match one or more actual arguments of any type (not necessarily the same type). These arguments will not be gathered into an array as happens with normal variadic functions; they will just be passed to the function separately. The PG_NARGS() macro and the methods described above must be used to determine the number of actual arguments and their types when using this feature.

ISBN 9781906966065The PostgreSQL 9.0 Reference Manual - Volume 2 - Programming GuideSee the print edition