Commit 96b8d584 authored by Michael Meskes's avatar Michael Meskes

Finally applied patch by Boszormenyi Zoltan <zb@cybertec.at> to add the new...

Finally applied patch by Boszormenyi Zoltan <zb@cybertec.at> to add the new features his patches added to the docs.
parent aa6ac352
<!-- $PostgreSQL: pgsql/doc/src/sgml/ecpg.sgml,v 1.93 2009/12/02 14:07:25 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/ecpg.sgml,v 1.94 2010/01/26 09:10:11 meskes Exp $ -->
<chapter id="ecpg">
<title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title>
......@@ -2376,6 +2376,478 @@ void PGTYPESdecimal_free(decimal *var);
</sect2>
</sect1>
<sect1 id="ecpg-descriptors">
<title>Using Descriptor Areas</title>
<para>
An SQL descriptor area is a more sophisticated method for processing
the result of a <command>SELECT</command>, <command>FETCH</command> or
a <command>DESCRIBE</command> statement. An SQL descriptor area groups
the data of one row of data together with metadata items into one
data structure. The metadata is particularly useful when executing
dynamic SQL statements, where the nature of the result columns might
not be known ahead of time. PostgreSQL provides two ways to use
Descriptor Areas: the named SQL Descriptor Areas and the C-structure
SQLDAs.
</para>
<sect2 id="ecpg-named-descriptors">
<title>Named SQL Descriptor Areas</title>
<para>
A named SQL descriptor area consists of a header, which contains
information concerning the entire descriptor, and one or more item
descriptor areas, which basically each describe one column in the
result row.
</para>
<para>
Before you can use an SQL descriptor area, you need to allocate one:
<programlisting>
EXEC SQL ALLOCATE DESCRIPTOR <replaceable>identifier</replaceable>;
</programlisting>
The identifier serves as the <quote>variable name</quote> of the
descriptor area. <remark>The scope of the allocated descriptor is WHAT?.</remark>
When you don't need the descriptor anymore, you should deallocate
it:
<programlisting>
EXEC SQL DEALLOCATE DESCRIPTOR <replaceable>identifier</replaceable>;
</programlisting>
</para>
<para>
To use a descriptor area, specify it as the storage target in an
<literal>INTO</literal> clause, instead of listing host variables:
<programlisting>
EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc;
</programlisting>
If the resultset is empty, the Descriptor Area will still contain
the metadata from the query, i.e. the field names.
</para>
<para>
For not yet executed prepared queries, the <command>DESCRIBE</command>
statement can be used to get the metadata of the resultset:
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
char *sql_stmt = "SELECT * FROM table1";
EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE stmt1 FROM :sql_stmt;
EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc;
</programlisting>
</para>
<para>
Before PostgreSQL 8.5, the <literal>SQL</literal> keyword was optional,
so using <literal>DESCRIPTOR</literal> and <literal>SQL DESCRIPTOR</literal>
produced named SQL Descriptor Areas. Now it is mandatory, omitting
the <literal>SQL</literal> keyword produces SQLDA Descriptor Areas,
see <xref linkend="ecpg-sqlda-descriptors">.
</para>
<para>
In <command>DESCRIBE</command> and <command>FETCH</command> statements,
the <literal>INTO</literal> and <literal>USING</literal> keywords can be
used to similarly: they produce the resultset and the metadata in a
Descriptor Area.
</para>
<para>
Now how do you get the data out of the descriptor area? You can
think of the descriptor area as a structure with named fields. To
retrieve the value of a field from the header and store it into a
host variable, use the following command:
<programlisting>
EXEC SQL GET DESCRIPTOR <replaceable>name</replaceable> :<replaceable>hostvar</replaceable> = <replaceable>field</replaceable>;
</programlisting>
Currently, there is only one header field defined:
<replaceable>COUNT</replaceable>, which tells how many item
descriptor areas exist (that is, how many columns are contained in
the result). The host variable needs to be of an integer type. To
get a field from the item descriptor area, use the following
command:
<programlisting>
EXEC SQL GET DESCRIPTOR <replaceable>name</replaceable> VALUE <replaceable>num</replaceable> :<replaceable>hostvar</replaceable> = <replaceable>field</replaceable>;
</programlisting>
<replaceable>num</replaceable> can be a literal integer or a host
variable containing an integer. Possible fields are:
<variablelist>
<varlistentry>
<term><literal>CARDINALITY</literal> (integer)</term>
<listitem>
<para>
number of rows in the result set
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATA</literal></term>
<listitem>
<para>
actual data item (therefore, the data type of this field
depends on the query)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATETIME_INTERVAL_CODE</literal> (integer)</term>
<listitem>
<para>
?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATETIME_INTERVAL_PRECISION</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>INDICATOR</literal> (integer)</term>
<listitem>
<para>
the indicator (indicating a null value or a value truncation)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>KEY_MEMBER</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the datum in characters
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>NAME</literal> (string)</term>
<listitem>
<para>
name of the column
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>NULLABLE</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OCTET_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the character representation of the datum in bytes
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>PRECISION</literal> (integer)</term>
<listitem>
<para>
precision (for type <type>numeric</type>)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RETURNED_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the datum in characters
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RETURNED_OCTET_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the character representation of the datum in bytes
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>SCALE</literal> (integer)</term>
<listitem>
<para>
scale (for type <type>numeric</type>)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>TYPE</literal> (integer)</term>
<listitem>
<para>
numeric code of the data type of the column
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
In <command>EXECUTE</command>, <command>DECLARE</command> and <command>OPEN</command>
statements, the effect of the <literal>INTO</literal> and <literal>USING</literal>
keywords are different. A Descriptor Area can also be manually built to
provide the input parameters for a query or a cursor and
<literal>USING SQL DESCRIPTOR <replaceable>name</replaceable></literal>
is the way to pass the input parameters into a parametrized query. The statement
to build a named SQL Descriptor Area is below:
<programlisting>
EXEC SQL SET DESCRIPTOR <replaceable>name</replaceable> VALUE <replaceable>num</replaceable> <replaceable>field</replaceable> = :<replaceable>hostvar</replaceable>;
</programlisting>
</para>
<para>
PostgreSQL supports retrieving more that one record in one <command>FETCH</command>
statement and storing the data in host variables in this case assumes that the
variable is an array. E.g.:
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
int id[5];
EXEC SQL END DECLARE SECTION;
EXEC SQL FETCH 5 FROM mycursor INTO SQL DESCRIPTOR mydesc;
EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA;
</programlisting>
</para>
</sect2>
<sect2 id="ecpg-sqlda-descriptors">
<title>SQLDA Descriptor Areas</title>
<para>
An SQLDA Descriptor Area is a C language structure which can be also used
to get the resultset and the metadata of a query. One structure stores one
record from the resultset.
<programlisting>
EXEC SQL include sqlda.h;
sqlda_t *mysqlda;
EXEC SQL FETCH 3 FROM mycursor INTO DESCRIPTOR mysqlda;
</programlisting>
Note that the <literal>SQL</literal> keyword is omitted. The paragraphs about
the use cases of the <literal>INTO</literal> and <literal>USING</literal>
keywords in <xref linkend="ecpg-named-descriptors"> also apply here with an addition.
In a <command>DESCRIBE</command> statement the <literal>DESCRIPTOR</literal>
keyword can be completely omitted if the <literal>INTO</literal> keyword is used:
<programlisting>
EXEC SQL DESCRIBE prepared_statement INTO mysqlda;
</programlisting>
</para>
<para>
The structure of SQLDA is:
<programlisting>
#define NAMEDATALEN 64
struct sqlname
{
short length;
char data[NAMEDATALEN];
};
struct sqlvar_struct
{
short sqltype;
short sqllen;
char *sqldata;
short *sqlind;
struct sqlname sqlname;
};
struct sqlda_struct
{
char sqldaid[8];
long sqldabc;
short sqln;
short sqld;
struct sqlda_struct *desc_next;
struct sqlvar_struct sqlvar[1];
};
typedef struct sqlvar_struct sqlvar_t;
typedef struct sqlda_struct sqlda_t;
</programlisting>
</para>
<para>
The allocated data for an SQLDA structure is variable as it depends on the
number of fields in a resultset and also depends on the length of the string
data values in a record. The individual fields of the <literal>SQLDA</literal>
structure are:
<variablelist>
<varlistentry>
<term><literal>sqldaid</></term>
<listitem>
<para>
It contains the "<literal>SQLDA </literal>" literal string.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqldabc</></term>
<listitem>
<para>
It contains the size of the allocated space in bytes.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqln</></term>
<listitem>
<para>
It contains the number of input parameters for a parametrized query
case it's passed into <command>OPEN</command>, <command>DECLARE</command> or
<command>EXECUTE</command> statements using the <literal>USING</literal>
keyword. In case it's used as output of <command>SELECT</command>,
<command>EXECUTE</command> or <command>FETCH</command> statements,
its value is the same as <literal>sqld</literal>
statement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqld</></term>
<listitem>
<para>
It contains the number of fields in a resultset.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>desc_next</></term>
<listitem>
<para>
If the query returns more than one records, multiple linked SQLDA structures
are returned, the first record is stored in the SQLDA returned in the
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlvar</></term>
<listitem>
<para>
This is the array of the fields in the resultset. The fields are:
<variablelist>
<varlistentry>
<term><literal>sqltype</></term>
<listitem>
<para>
It contains the type identifier of the field. For values,
see <literal>enum ECPGttype</literal> in <literal>ecpgtype.h</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqllen</></term>
<listitem>
<para>
It contains the binary length of the field. E.g. 4 bytes for ECPGt_int.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqldata</></term>
<listitem>
<para>
<literal>(char *)sqldata</literal> points to the data.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlind</></term>
<listitem>
<para>
<literal>(char *)sqlind</literal> points to the NULL indicator for data.
0 means NOT NULL, -1 means NULL.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlname</></term>
<listitem>
<para>
<literal>struct sqlname sqlname</literal> contains the name of the field
in a structure:
<programlisting>
struct sqlname
{
short length;
char data[NAMEDATALEN];
};
</programlisting>
<variablelist>
<varlistentry>
<term><literal>length</></term>
<listitem>
<para>
<literal>sqlname.length</literal> contains the length of the field name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>data</></term>
<listitem>
<para>
<literal>sqlname.data</literal> contains the actual field name.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
</sect1>
<sect1 id="ecpg-informix-compat">
<title><productname>Informix</productname> compatibility mode</title>
<para>
......@@ -2385,58 +2857,373 @@ void PGTYPESdecimal_free(decimal *var);
the dollar sign instead of the <literal>EXEC SQL</> primitive to introduce
embedded SQL commands.:
<programlisting>
$int j = 3;
$CONNECT TO :dbname;
$CREATE TABLE test(i INT PRIMARY KEY, j INT);
$INSERT INTO test(i, j) VALUES (7, :j);
$COMMIT;
$int j = 3;
$CONNECT TO :dbname;
$CREATE TABLE test(i INT PRIMARY KEY, j INT);
$INSERT INTO test(i, j) VALUES (7, :j);
$COMMIT;
</programlisting>
</para>
<para>
There are two compatiblity modes: INFORMIX, INFORMIX_SE
</para>
<para>
When linking programs that use this compatibility mode, remember to link
against <literal>libcompat</> that is shipped with ecpg.
</para>
<para>
Besides the previously explained syntactic sugar, the <productname>Informix</productname> compatibility
mode ports some functions for input, output and transformation of data as
well as embedded SQL statements known from E/SQL to ecpg.
</para>
<para>
<productname>Informix</productname> compatibility mode is closely connected to the pgtypeslib library
of ecpg. pgtypeslib maps SQL data types to data types within the C host
program and most of the additional functions of the <productname>Informix</productname> compatibility
mode allow you to operate on those C host program types. Note however that
the extent of the compatibility is limited. It does not try to copy <productname>Informix</productname>
behaviour; it allows you to do more or less the same operations and gives
you functions that have the same name and the same basic behavior but it is
no drop-in replacement if you are using <productname>Informix</productname> at the moment. Moreover,
some of the data types are different. For example,
<productname>PostgreSQL's</productname> datetime and interval types do not
know about ranges like for example <literal>YEAR TO MINUTE</> so you won't
find support in ecpg for that either.
</para>
<sect2>
<title>Additional types</title>
<para>
The Informix-special "string" pseudo-type for storing right-trimmed character string data is now
supported in Informix-mode without using <literal>typedef</literal>. In fact, in Informix-mode,
ECPG refuses to process source files that contain <literal>typedef sometype string;</literal>
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
string userid; /* this variable will contain trimmed data */
EXEC SQL END DECLARE SECTION;
EXEC SQL FETCH MYCUR INTO :userid;
</programlisting>
</para>
</sect2>
<sect2>
<title>Additional/missing embedded SQL statements</title>
<para>
<variablelist>
<varlistentry>
<term><literal>CLOSE DATABASE</></term>
<listitem>
<para>
This statement closes the current connection. In fact, this is a
synonym for ecpg's <literal>DISCONNECT CURRENT</>.:
<programlisting>
$CLOSE DATABASE; /* close the current connection */
EXEC SQL CLOSE DATABASE;
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>FREE cursor_name</></term>
<listitem>
<para>
Due to the differences how ECPG works compared to Informix's ESQL/C (i.e. which steps
are purely grammar transformations and which steps rely on the underlying runtime library)
there is no <literal>FREE cursor_name</> statement in ECPG. This is because in ECPG,
<literal>DECLARE CURSOR</literal> doesn't translate to a function call into
the runtime library that uses to the cursor name. This means that there's no runtime
bookkeeping of SQL cursors in the ECPG runtime library, only in the PostgreSQL server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>FREE statement_name</></term>
<listitem>
<para>
<literal>FREE statement_name</> is a synonym for <literal>DEALLOCATE PREPARE statement_name</>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>Informix-compatible SQLDA Descriptor Areas</title>
<para>
Informix-compatible mode supports a different structure than the one described in
<xref linkend="ecpg-sqlda-descriptors">. See below:
<programlisting>
struct sqlvar_compat
{
short sqltype;
int sqllen;
char *sqldata;
short *sqlind;
char *sqlname;
char *sqlformat;
short sqlitype;
short sqlilen;
char *sqlidata;
int sqlxid;
char *sqltypename;
short sqltypelen;
short sqlownerlen;
short sqlsourcetype;
char *sqlownername;
int sqlsourceid;
char *sqlilongdata;
int sqlflags;
void *sqlreserved;
};
struct sqlda_compat
{
short sqld;
struct sqlvar_compat *sqlvar;
char desc_name[19];
short desc_occ;
struct sqlda_compat *desc_next;
void *reserved;
};
typedef struct sqlvar_compat sqlvar_t;
typedef struct sqlda_compat sqlda_t;
</programlisting>
</para>
<para>
The global properties are:
<variablelist>
<varlistentry>
<term><literal>sqld</></term>
<listitem>
<para>
The number of fields in the <literal>SQLDA</> descriptor.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlvar</></term>
<listitem>
<para>
Pointer to the per-field properties.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>desc_name</></term>
<listitem>
<para>
Unused, filled with zerobytes.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>desc_occ</></term>
<listitem>
<para>
Size of the allocated structure.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>desc_next</></term>
<listitem>
<para>
Pointer to the next SQLDA structure if the resultset contains more than one records.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>reserved</></term>
<listitem>
<para>
Unused pointer, contains NULL. Kept for Informix-compatibility.
</para>
</listitem>
</varlistentry>
</variablelist>
The per-field properties are below, they are stored in the <literal>sqlvar</literal> array:
<variablelist>
<varlistentry>
<term><literal>sqltype</></term>
<listitem>
<para>
Type of the field. Constants are in <literal>sqltypes.h</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqllen</></term>
<listitem>
<para>
Length of the field data.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqldata</></term>
<listitem>
<para>
Pointer to the field data. The pointer is of <literal>char *</literal> type,
the data pointed by it is in a binary format. Example:
<programlisting>
int intval;
switch (sqldata->sqlvar[i].sqltype)
{
case SQLINTEGER:
intval = *(int *)sqldata->sqlvar[i].sqldata;
break;
...
}
</programlisting>
</para>
<para>
There are two compatiblity modes: INFORMIX, INFORMIX_SE
</para>
<para>
When linking programs that use this compatibility mode, remember to link
against <literal>libcompat</> that is shipped with ecpg.
</para>
<para>
Besides the previously explained syntactic sugar, the <productname>Informix</productname> compatibility
mode ports some functions for input, output and transformation of data as
well as embedded SQL statements known from E/SQL to ecpg.
</para>
<para>
<productname>Informix</productname> compatibility mode is closely connected to the pgtypeslib library
of ecpg. pgtypeslib maps SQL data types to data types within the C host
program and most of the additional functions of the <productname>Informix</productname> compatibility
mode allow you to operate on those C host program types. Note however that
the extent of the compatibility is limited. It does not try to copy <productname>Informix</productname>
behaviour; it allows you to do more or less the same operations and gives
you functions that have the same name and the same basic behavior but it is
no drop-in replacement if you are using <productname>Informix</productname> at the moment. Moreover,
some of the data types are different. For example,
<productname>PostgreSQL's</productname> datetime and interval types do not
know about ranges like for example <literal>YEAR TO MINUTE</> so you won't
find support in ecpg for that either.
</para>
</para>
</listitem>
</varlistentry>
<sect2>
<title>Additional embedded SQL statements</title>
<para>
<variablelist>
<varlistentry>
<term><literal>CLOSE DATABASE</></term>
<term><literal>sqlind</></term>
<listitem>
<para>
This statement closes the current connection. In fact, this is a
synonym for ecpg's <literal>DISCONNECT CURRENT</>.:
Pointer to the NULL indicator. If returned by DESCRIBE or FETCH then it's always a valid pointer.
If used as input for <literal>EXECUTE ... USING sqlda;</literal> then NULL-pointer value means
that the value for this field is non-NULL. Otherwise a valid pointer and <literal>sqlitype</literal>
has to be properly set. Example:
<programlisting>
$CLOSE DATABASE; /* close the current connection */
EXEC SQL CLOSE DATABASE;
if (*(int2 *)sqldata->sqlvar[i].sqlind != 0)
printf("value is NULL\n");
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlname</></term>
<listitem>
<para>
Name of the field. 0-terminated string.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlformat</></term>
<listitem>
<para>
Reserved in Informix, value of PQfformat() for the field.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlitype</></term>
<listitem>
<para>
Type of the NULL indicator data. It's always SQLSMINT when returning data from the server.
When the <literal>SQLDA</literal> is used for a parametrized query, the data is treated
according to the set type.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlilen</></term>
<listitem>
<para>
Length of the NULL indicator data.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlxid</></term>
<listitem>
<para>
Extended type of the field, result of PQftype().
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqltypename</></term>
<term><literal>sqltypelen</></term>
<term><literal>sqlownerlen</></term>
<term><literal>sqlsourcetype</></term>
<term><literal>sqlownername</></term>
<term><literal>sqlsourceid</></term>
<term><literal>sqlflags</></term>
<term><literal>sqlreserved</></term>
<listitem>
<para>
Unused.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>sqlilongdata</></term>
<listitem>
<para>
It equals to <literal>sqldata</literal> if <literal>sqllen</literal> is larger than 32KB.
</para>
</listitem>
</varlistentry>
</variablelist>
Example:
<programlisting>
EXEC SQL INCLUDE sqlda.h;
sqlda_t *sqlda; /* This doesn't need to be under embedded DECLARE SECTION */
EXEC SQL BEGIN DECLARE SECTION;
char *prep_stmt = "select * from table1";
int i;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL PREPARE mystmt FROM :prep_stmt;
EXEC SQL DESCRIBE mystmt INTO sqlda;
printf("# of fields: %d\n", sqlda->sqld);
for (i = 0; i < sqlda->sqld; i++)
printf("field %d: \"%s\"\n", sqlda->sqlvar[i]->sqlname);
EXEC SQL DECLARE mycursor CURSOR FOR mystmt;
EXEC SQL OPEN mycursor;
EXEC SQL WHENEVER NOT FOUND GOTO out;
while (1)
{
EXEC SQL FETCH mycursor USING sqlda;
}
EXEC SQL CLOSE mycursor;
free(sqlda); /* The main structure is all to be free(),
* sqlda and sqlda->sqlvar is in one allocated area */
</programlisting>
For more information, see the <literal>sqlda.h</> header and the
<literal>src/interfaces/ecpg/test/compat_informix/sqlda.pgc</literal> regression test.
</para>
</sect2>
......@@ -3660,208 +4447,6 @@ risnull(CINTTYPE, (char *) &i);
</sect2>
</sect1>
<sect1 id="ecpg-descriptors">
<title>Using SQL Descriptor Areas</title>
<para>
An SQL descriptor area is a more sophisticated method for
processing the result of a <command>SELECT</command> or
<command>FETCH</command> statement. An SQL descriptor area groups
the data of one row of data together with metadata items into one
data structure. The metadata is particularly useful when executing
dynamic SQL statements, where the nature of the result columns might
not be known ahead of time.
</para>
<para>
An SQL descriptor area consists of a header, which contains
information concerning the entire descriptor, and one or more item
descriptor areas, which basically each describe one column in the
result row.
</para>
<para>
Before you can use an SQL descriptor area, you need to allocate one:
<programlisting>
EXEC SQL ALLOCATE DESCRIPTOR <replaceable>identifier</replaceable>;
</programlisting>
The identifier serves as the <quote>variable name</quote> of the
descriptor area. <remark>The scope of the allocated descriptor is WHAT?.</remark>
When you don't need the descriptor anymore, you should deallocate
it:
<programlisting>
EXEC SQL DEALLOCATE DESCRIPTOR <replaceable>identifier</replaceable>;
</programlisting>
</para>
<para>
To use a descriptor area, specify it as the storage target in an
<literal>INTO</literal> clause, instead of listing host variables:
<programlisting>
EXEC SQL FETCH NEXT FROM mycursor INTO DESCRIPTOR mydesc;
</programlisting>
</para>
<para>
Now how do you get the data out of the descriptor area? You can
think of the descriptor area as a structure with named fields. To
retrieve the value of a field from the header and store it into a
host variable, use the following command:
<programlisting>
EXEC SQL GET DESCRIPTOR <replaceable>name</replaceable> :<replaceable>hostvar</replaceable> = <replaceable>field</replaceable>;
</programlisting>
Currently, there is only one header field defined:
<replaceable>COUNT</replaceable>, which tells how many item
descriptor areas exist (that is, how many columns are contained in
the result). The host variable needs to be of an integer type. To
get a field from the item descriptor area, use the following
command:
<programlisting>
EXEC SQL GET DESCRIPTOR <replaceable>name</replaceable> VALUE <replaceable>num</replaceable> :<replaceable>hostvar</replaceable> = <replaceable>field</replaceable>;
</programlisting>
<replaceable>num</replaceable> can be a literal integer or a host
variable containing an integer. Possible fields are:
<variablelist>
<varlistentry>
<term><literal>CARDINALITY</literal> (integer)</term>
<listitem>
<para>
number of rows in the result set
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATA</literal></term>
<listitem>
<para>
actual data item (therefore, the data type of this field
depends on the query)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATETIME_INTERVAL_CODE</literal> (integer)</term>
<listitem>
<para>
?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>DATETIME_INTERVAL_PRECISION</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>INDICATOR</literal> (integer)</term>
<listitem>
<para>
the indicator (indicating a null value or a value truncation)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>KEY_MEMBER</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the datum in characters
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>NAME</literal> (string)</term>
<listitem>
<para>
name of the column
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>NULLABLE</literal> (integer)</term>
<listitem>
<para>
not implemented
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OCTET_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the character representation of the datum in bytes
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>PRECISION</literal> (integer)</term>
<listitem>
<para>
precision (for type <type>numeric</type>)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RETURNED_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the datum in characters
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RETURNED_OCTET_LENGTH</literal> (integer)</term>
<listitem>
<para>
length of the character representation of the datum in bytes
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>SCALE</literal> (integer)</term>
<listitem>
<para>
scale (for type <type>numeric</type>)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>TYPE</literal> (integer)</term>
<listitem>
<para>
numeric code of the data type of the column
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect1>
<sect1 id="ecpg-errors">
<title>Error Handling</title>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment