id="ecpg-variables-nonprimitive-c-typedefs">
<title>Typedefs</title>
<indexterm>
<primary>typedef</primary>
<secondary>in ECPG</secondary>
</indexterm>
<para>
Use the <literal>typedef</literal> keyword to map new types to already
existing types.
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
typedef char mychartype[40];
typedef long serial_t;
EXEC SQL END DECLARE SECTION;
</programlisting>
Note that you could also use:
<programlisting>
EXEC SQL TYPE serial_t IS long;
</programlisting>
This declaration does not need to be part of a declare section;
that is, you can also write typedefs as normal C statements.
</para>
<para>
Any word you declare as a <literal>typedef</literal> cannot be used as
an SQL keyword in <literal>EXEC SQL</literal> commands later in the same
program. For example, this won't work:
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
typedef int start;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL START TRANSACTION;
</programlisting>
ECPG will report a syntax error for <literal>START
TRANSACTION</literal>, because it no longer
recognizes <literal>START</literal> as an SQL keyword,
only as a typedef.
(If you have such a conflict, and renaming the typedef
seems impractical, you could write the SQL command
using <link linkend="ecpg-dynamic">dynamic SQL</link>.)
</para>
<note>
<para>
In <productname>PostgreSQL</productname> releases before v16, use
of SQL keywords as typedef names was likely to result in syntax
errors associated with use of the typedef itself, rather than use
of the name as an SQL keyword. The new behavior is less likely to
cause problems when an existing ECPG application is recompiled in
a new <productname>PostgreSQL</productname> release with new
keywords.
</para>
</note>
</sect4>
<sect4 id="ecpg-variables-nonprimitive-c-pointers">
<title>Pointers</title>
<para>
You can declare pointers to the most common types. Note however
that you cannot use pointers as target variables of queries
without auto-allocation. See <xref linkend="ecpg-descriptors"/>
for more information on auto-allocation.
</para>
<para>
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
int *intp;
char **charp;
EXEC SQL END DECLARE SECTION;
</programlisting>
</para>
</sect4>
</sect3>
</sect2>
<sect2 id="ecpg-variables-nonprimitive-sql">
<title>Handling Nonprimitive SQL Data Types</title>
<para>
This section contains information on how to handle nonscalar and
user-defined SQL-level data types in ECPG applications. Note that
this is distinct from the handling of host variables of
nonprimitive types, described in the previous section.
</para>
<sect3 id="ecpg-variables-nonprimitive-sql-arrays">
<title>Arrays</title>
<para>
Multi-dimensional SQL-level arrays are not directly supported in ECPG.
One-dimensional SQL-level arrays can be mapped into C array host
variables and vice-versa. However, when creating a statement ecpg does
not know the types of the columns, so that it cannot check if a C array
is input into a corresponding SQL-level array. When processing the
output of an SQL statement, ecpg has the necessary information and thus
checks if both are arrays.
</para>
<para>
If a query accesses <emphasis>elements</emphasis> of an array
separately, then this avoids the use of arrays in ECPG. Then, a
host variable with a type that can be mapped to the element type
should be used. For example, if a column type is array of
<type>integer</type>, a host variable of type <type>int</type>
can be used. Also if the element type is <type>varchar</type>
or <type>text</type>, a host variable of type <type>char[]</type>
or <type>VARCHAR[]</type>