</programlisting>
</para>
<para>
Finally, we can provide the full definition of the data type:
<programlisting>
CREATE TYPE complex (
internallength = 16,
input = complex_in,
output = complex_out,
receive = complex_recv,
send = complex_send,
alignment = double
);
</programlisting>
</para>
<para>
<indexterm>
<primary>array</primary>
<secondary>of user-defined type</secondary>
</indexterm>
When you define a new base type,
<productname>PostgreSQL</productname> automatically provides support
for arrays of that type. The array type typically
has the same name as the base type with the underscore character
(<literal>_</literal>) prepended.
</para>
<para>
Once the data type exists, we can declare additional functions to
provide useful operations on the data type. Operators can then be
defined atop the functions, and if needed, operator classes can be
created to support indexing of the data type. These additional
layers are discussed in following sections.
</para>
<para>
If the internal representation of the data type is variable-length, the
internal representation must follow the standard layout for variable-length
data: the first four bytes must be a <type>char[4]</type> field which is
never accessed directly (customarily named <structfield>vl_len_</structfield>). You
must use the <function>SET_VARSIZE()</function> macro to store the total
size of the datum (including the length field itself) in this field
and <function>VARSIZE()</function> to retrieve it. (These macros exist
because the length field may be encoded depending on platform.)
</para>
<para>
For further details see the description of the
<xref linkend="sql-createtype"/> command.
</para>
<sect2 id="xtypes-toast">
<title>TOAST Considerations</title>
<indexterm>
<primary>TOAST</primary>
<secondary>and user-defined types</secondary>
</indexterm>
<para>
If the values of your data type vary in size (in internal form), it's
usually desirable to make the data type <acronym>TOAST</acronym>-able (see <xref
linkend="storage-toast"/>). You should do this even if the values are always
too small to be compressed or stored externally, because
<acronym>TOAST</acronym> can save space on small data too, by reducing header
overhead.
</para>
<para>
To support <acronym>TOAST</acronym> storage, the C functions operating on the data
type must always be careful to unpack any toasted values they are handed
by using <function>PG_DETOAST_DATUM</function>. (This detail is customarily hidden
by defining type-specific <function>GETARG_DATATYPE_P</function> macros.)
Then, when running the <command>CREATE TYPE</command> command, specify the
internal length as <literal>variable</literal> and select some appropriate storage
option other than <literal>plain</literal>.
</para>
<para>
If data alignment is unimportant (either just for a specific function or
because the data type specifies byte alignment anyway) then it's possible
to avoid some of the overhead of <function>PG_DETOAST_DATUM</function>. You can use
<function>PG_DETOAST_DATUM_PACKED</function> instead (customarily hidden by
defining a <function>GETARG_DATATYPE_PP</function> macro) and using the macros
<function>VARSIZE_ANY_EXHDR</function> and <function>VARDATA_ANY</function> to access
a potentially-packed datum.
Again, the data returned by these macros is not aligned even if the data
type definition specifies an alignment. If the alignment is important you
must go through the regular <function>PG_DETOAST_DATUM</function> interface.
</para>
<note>
<para>
Older code frequently declares <structfield>vl_len_</structfield> as an
<type>int32</type> field instead of <type>char[4]</type>. This is OK as long as
the struct definition has other fields that have at least <type>int32</type>
alignment. But it is dangerous to use such a struct definition when
working with a potentially