converted into a named struct for every
variable. A declaration like:
<programlisting>
bytea var[180];
</programlisting>
is converted into:
<programlisting>
struct bytea_var { int len; char arr[180]; } var;
</programlisting>
The member <structfield>arr</structfield> hosts binary format
data. It can also handle <literal>'\0'</literal> as part of
data, unlike <type>VARCHAR</type>.
The data is converted from/to hex format and sent/received by
ecpglib.
</para>
<note>
<para>
<type>bytea</type> variable can be used only when
<xref linkend="guc-bytea-output"/> is set to <literal>hex</literal>.
</para>
</note>
</sect4>
</sect3>
<sect3 id="ecpg-variables-nonprimitive-c">
<title>Host Variables with Nonprimitive Types</title>
<para>
As a host variable you can also use arrays, typedefs, structs, and
pointers.
</para>
<sect4 id="ecpg-variables-arrays">
<title>Arrays</title>
<para>
There are two use cases for arrays as host variables. The first
is a way to store some text string in <type>char[]</type>
or <type>VARCHAR[]</type>, as
explained in <xref linkend="ecpg-char"/>. The second use case is to
retrieve multiple rows from a query result without using a
cursor. Without an array, to process a query result consisting
of multiple rows, it is required to use a cursor and
the <command>FETCH</command> command. But with array host
variables, multiple rows can be received at once. The length of
the array has to be defined to be able to accommodate all rows,
otherwise a buffer overflow will likely occur.
</para>
<para>
Following example scans the <literal>pg_database</literal>
system table and shows all OIDs and names of the available
databases:
<programlisting>
int
main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int dbid[8];
char dbname[8][16];
int i;
EXEC SQL END DECLARE SECTION;
memset(dbname, 0, sizeof(char)* 16 * 8);
memset(dbid, 0, sizeof(int) * 8);
EXEC SQL CONNECT TO testdb;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
/* Retrieve multiple rows into arrays at once. */
EXEC SQL SELECT oid,datname INTO :dbid, :dbname FROM pg_database;
for (i = 0; i < 8; i++)
printf("oid=%d, dbname=%s\n", dbid[i], dbname[i]);
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
}
</programlisting>
This example shows following result. (The exact values depend on
local circumstances.)
<screen>
oid=1, dbname=template1
oid=11510, dbname=template0
oid=11511, dbname=postgres
oid=313780, dbname=testdb
oid=0, dbname=
oid=0, dbname=
oid=0, dbname=
</screen>
</para>
</sect4>
<sect4 id="ecpg-variables-struct">
<title>Structures</title>
<para>
A structure whose member names match the column names of a query
result, can 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,