How to Declare an SQLDA Record Variable
Once you have included (or hard-coded) the SQLDA type definition, the program can declare an SQLDA record variable. You must declare this record variable outside of a declare section, as the preprocessor does not understand the special meaning of the SQLDA record or the IISQLDA record type. When you use the variable in the context of a Dynamic SQL or Dynamic FRS statement, the preprocessor accepts any object name, and assumes that the variable refers to a legally declared SQLDA record variable, for which storage has been allocated.
If your program requires an SQLDA variable with IISQ_MAX_COLS sqlvar elements, you can accomplish this by declaring the variable without a discriminant constraint. Unlike other languages, an Ada program cannot set the value of sqln. Because sqln is a type discriminant, its value is implicit from the declaration.
For example:
exec sql include sqlda;
sqlda: IISQLDA;
-- Default sets sqlda.sqln to IISQ_MAX_COLS
-- This is outside of a DECLARE SECTION.
...
exec sql describe s1 into :sqlda;
However, when you do not use a discriminant constraint in the record declaration, you cannot later use an Ada renames statement as a shorthand into the sqlvar array. A shorthand can be desirable over continued long references such as:
sqlda.sqlvar(i).sqldata
sqlda.sqlvar(i).sqlname.sqlnamec
For example, the above declaration of the SQLDA is equivalent to:
exec sql include sqlda;
max_sqlda: IISQLDA(IISQ_MAX_COLS); -- Includes constraint
...
exec sql describe s1 into :max_sqlda;
...
for i in 1..max_sqlda.sqld loop;
declare
sqv: IISQL_VAR renames max_sqlda.sqlvar(i);
begin
-- Use shorthand sqv instead of
-- max_sqlda.sqlvar(i)
end;
end loop;
If you require an SQLDA with a different number of sqlvar elements, then you can use a different discriminant constraint. For example:
sqlda_10:IISQLDA(10); -- Implicitly sets sqlda.sqln to 10
You can also dynamically allocate an SQLDA with a varying number of sqlvar elements. In the following example an SQLDA access variable is declared. Note that when you reference the variable in the describe statement the Ada all clause is used, as the preprocessor expects a valid SQLDA record variable and not a pointer to a record:
exec sql include sqlda;
procedure Process_Dynamic_SQL (num_cols: in
Short_Integer) is
type SQLDA_PTR is access IISQLDA;
sp: SQLDA_PTR;
begin
sp := new SQLDA_PTR(num_cols);
...
exec sql describe s1 INTO :sp.all; -- Note .all
...
end Process_Dynamic_SQL;
As long as you use the IISQLDA record type, or a derivative of that type, you need not be concerned with the SQLDA record layout. When you code your own SQLDA record type then you must confirm that the internal record layout is identical to that of the IISQLDA record. One reason you might code your own SQLDA record type is to avoid the runtime overhead required to validate offsets into a record variable containing a varying length array, such as sqlvar.
You may prefer a fixed length record variable without a discriminant. In that case you must declare the sqln component in the correct position, and you must explicitly set the value of sqln in order for the describe statement to succeed. For example:
max_sq: constant := 50;
type fixed_sqlda_max is -- Layout is correct
record
my_sqid: String(1..8);
my_sqbc: Integer;
my_vars: Short_Integer; -- Equivalent to sqln
res_vars: Short_Integer; -- and SQLD
col_vars: IISQL_VARS(1..MAX_SQ);
end record;
my_sq: FIXED_SQLDA_MAX;
...
my_sq.my_vars := MAX_SQ; -- Size must be set
...
exec sql describe s1 into :my_sq;
In the above record type definition, the names of the record components are not the same as those of the IISQLDA record, but their layout is identical.
As shown above there are a variety of ways to declare an SQLDA record variable. Names of record components are not important; internal component layout, however, is critical.
Last modified date: 01/30/2023