Base Types in C-Language Functions

The following table gives the C type required for parameters in the C functions that will be loaded into PostgreSQL. The "Defined In" column gives the actual header file (in the PGROOT/src/backend/ directory) where the equivalent C type is defined. Note that you should always include postgres.h first, and that in turn includes c.h.

Table 10-1. Equivalent C Types for Built-In PostgreSQL Types

Built-In TypeC TypeDefined In
abstimeAbsoluteTimeutils/nabstime.h
boolboolinclude/c.h
box(BOX *)utils/geo-decls.h
bytea(bytea *)include/postgres.h
"char"charN/A
cidCIDinclude/postgres.h
datetime(DateTime *)include/c.h or include/postgres.h
int2int2 or int16include/postgres.h
int2vector(int2vector *)include/postgres.h
int4int4 or int32include/postgres.h
float4(float4 *)include/c.h or include/postgres.h
float8(float8 *)include/c.h or include/postgres.h
lseg(LSEG *)include/geo-decls.h
name(Name)include/postgres.h
oidoidinclude/postgres.h
oidvector(oidvector *)include/postgres.h
path(PATH *)utils/geo-decls.h
point(POINT *)utils/geo-decls.h
regprocregproc or REGPROCinclude/postgres.h
reltimeRelativeTimeutils/nabstime.h
text(text *)include/postgres.h
tidItemPointerstorage/itemptr.h
timespan(TimeSpan *)include/c.h or include/postgres.h
tintervalTimeIntervalutils/nabstime.h
xid(XID *)include/postgres.h

Internally, PostgreSQL regards a base type as a "blob of memory." The user-defined functions that you define over a type in turn define the way that PostgreSQL can operate on it. That is, PostgreSQL will store and retrieve only the data from disk and use your user-defined functions to input, process, and output the data. Base types can have one of three internal formats:

By-value types can be only 1, 2 or 4 bytes in length (also 8 bytes, if sizeof(Datum) is 8 on your machine). You should be careful to define your types such that they will be the same size (in bytes) on all architectures. For example, the long type is dangerous because it is 4 bytes on some machines and 8 bytes on others, whereas int type is 4 bytes on most Unix machines (though not on most personal computers). A reasonable implementation of the int4 type on Unix machines might be:
/* 4-byte integer, passed by value */
typedef int int4;

On the other hand, fixed-length types of any size may be passed by-reference. For example, here is a sample implementation of a PostgreSQL type:
/* 16-byte structure, passed by reference */
typedef struct
{
    double  x, y;
} Point;

Only pointers to such types can be used when passing them in and out of PostgreSQL functions. To return a value of such a type, allocate the right amount of memory with palloc(), fill in the allocated memory, and return a pointer to it. (Alternatively, you can return an input value of the same type by returning its pointer. Never modify the contents of a pass-by-reference input value, however.)

Finally, all variable-length types must also be passed by reference. All variable-length types must begin with a length field of exactly 4 bytes (VARHDRSZ), and all data to be stored within that type must be located in the memory immediately following that length field. The length field is the total length of the structure (that is, it includes the size of the length field itself). We could define the text type as follows:
typedef struct {
    int4 length;
    char data[1];
} text;

Obviously, the data field shown here is not long enough to hold all possible strings; it is impossible to declare such a structure in C. When manipulating variable-length types, we must be careful to allocate the correct amount of memory and initialize the length field. For example, if we wanted to store 40 bytes in a text structure, we could use a code fragment like this:
#include "postgres.h"
...
char buffer[40]; /* our source data */
...
text *destination = (text *) palloc(VARHDRSZ + 40);
destination->length = VARHDRSZ + 40;
memmove(destination->data, buffer, 40);
...