be used to retrieve multiple columns at once. The
structure enables handling multiple column values in a single
host variable.
</para>
<para>
The following example retrieves OIDs, names, and sizes of the
available databases from the <literal>pg_database</literal>
system table and using
the <function>pg_database_size()</function> function. In this
example, a structure variable <varname>dbinfo_t</varname> with
members whose names match each column in
the <literal>SELECT</literal> result is used to retrieve one
result row without putting multiple host variables in
the <literal>FETCH</literal> statement.
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
long long int size;
} dbinfo_t;
dbinfo_t dbval;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* when end of result set reached, break out of while loop */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* Fetch multiple columns into one structure. */
EXEC SQL FETCH FROM cur1 INTO :dbval;
/* Print members of the structure. */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, dbval.size);
}
EXEC SQL CLOSE cur1;
</programlisting>
</para>
<para>
This example shows following result. (The exact values depend on
local circumstances.)
<screen>
oid=1, datname=template1, size=4324580
oid=11510, datname=template0, size=4243460
oid=11511, datname=postgres, size=4324580
oid=313780, datname=testdb, size=8183012
</screen>
</para>
<para>
Structure host variables <quote>absorb</quote> as many columns
as the structure as fields. Additional columns can be assigned
to other host variables. For example, the above program could
also be restructured like this, with the <varname>size</varname>
variable outside the structure:
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
} dbinfo_t;
dbinfo_t dbval;
long long int size;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* when end of result set reached, break out of while loop */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* Fetch multiple columns into one structure. */
EXEC SQL FETCH FROM cur1 INTO :dbval, :size;
/* Print members of the structure. */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, size);
}
EXEC SQL CLOSE cur1;
</programlisting>
</para>
</sect4>
<sect4 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;