Dynamic Operations [ ALLBASE/SQL Pascal Application Programming Guide ] MPE/iX 5.0 Documentation
ALLBASE/SQL Pascal Application Programming Guide
Dynamic Operations
Dynamic operations offer a way to execute SQL commands that cannot be
completely defined until run time. You accept part or all of an SQL
command that can be dynamically preprocessed from the user, then use one
of the following techniques to preprocess and execute the command:
* If the dynamic command is not a query, you can use the PREPARE
command to preprocess it, then execute it later during the same
transaction using the EXECUTE command. Alternatively, you can use
the EXECUTE IMMEDIATE command to preprocess and execute the
dynamic command in one step.
* If the dynamic command is a query, you use special data structures
plus the following SQL commands to handle the dynamic command:
PREPARE, DESCRIBE, DECLARE CURSOR, OPEN, FETCH, and CLOSE.
To determine whether a dynamic command is a query, you use the DESCRIBE
command after preparing the dynamic command:
The program accepts an SQL command from the user and stores
it in a host variable named DynamicCommand.
EXEC SQL PREPARE DynamCommand FROM :DynamicCommand;
After the command is prepared, the DESCRIBE command is used
to determine whether the prepared command is a SELECT command.
EXEC SQL DESCRIBE DynamCommand INTO SQLDA;
The SQLDA.SQLD field of the SQLDA is examined to determine
whether the dynamic command is a query.
if SQLDA.SQLD = 0 then (*the command is not a query*)
begin
EXEC SQL EXECUTE DynamCommand;
.
.
.
else if SQLDA.SQLD > 0 then (*the command is a query*)
.
.
.
A non-query can be executed with the EXECUTE
command, but a query requires special handling.
Dynamic queries require special handling because you may not know in
advance what a query result will look like. The number and type of
columns, the existence of null values, the column names...this and other
information may need to be obtained by the program at run time because it
is not known at programming time.
To obtain the information needed to parse any query result at run time,
you use three special data structures in your program: the SQLDA, a
format array, and a data buffer:
* The SQLDA (SQL Description Area) and the format array contain
information about the query result. These data structures have
the format described in the chapter, "Host Variables."
* The data buffer holds one or more rows fetched from the query
result. Its format is also described in the chapter, "Host
Variables."
The following example summarizes how you declare and use these data
structures:
const
OK = 0;
Notfound = 100;
NbrFmtRecords = 255; (*maximum number of columns*)
MaxDataBuff = 1600; (*maximum number of bytes the program*)
(*allows in each fetch; 1600 bytes *)
(*accommodates the display of 20*)
(*80-character lines*)
var
EXEC SQL BEGIN DECLARE SECTION;
DynamicCommand : String[1024] (*maximum length of*)
(*a dynamic command*)
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLDA;
(*declaration of SQLDA*)
SQLFmts : array[1..NbrFmtRecords] of SqlFormat_Type;
(*declaration of format array*)
DataBuffer : packed array[1..MaxDataBuff] of char;
(*declaration of data buffer*)
:
procedure ExecuteDynamCmd;
begin
with SQLDA do (*You must set two SQLDA fields before DESCRIBE*)
begin
Sqln := NbrFmtRecords; (*number of records in format array*)
SqlFmtArr := waddress(SQLFmts); (*address of format array*)
end;
.
. The program accepts a dynamic command.
EXEC SQL PREPARE DYNAMCOMMAND FROM :DYNAMICCOMMAND;
.
. Status checking is done.
EXEC SQL DESCRIBE DYNAMCOMMAND INTO SQLDA;
if SQLDA.SQLD = 0 (*dynamic command is not a query*)
.
. The program executes the dynamic command.
.
else if SQLDA.SQLD > 0 then (*dynamic command is a query*)
begin
EXEC SQL DECLARE DYNAMCURSOR CURSOR FOR DYNAMCOMMAND;
EXEC SQL OPEN DYNAMCURSOR;
.
. If SQLCODE is 0, rows in the query result can be
fetched. First, however, you must set three
SQLDA fields.
with SQLDA do
begin
SqlBufLen := sizeof(DataBuffer); (*bytes in data buffer*)
SqlNRow := SqlBufLen DIV SqlRowLen;
(*number of rows to fetch into data buffer*)
SqlRowBuf := waddress(DataBuffer); (*address of data buffer*)
end;
while SQLCA.SQLCODE = OK do
begin
EXEC SQL FETCH DYNAMCURSOR USING DESCRIPTOR SQLDA;
if SQLCA.SQLCODE <> OK then
begin
if SQLCA.SQLCODE = NotFound then
writeln('No more rows qualify.')
else
SQLStatusCheck;
end;
else
DisplaySelect;
end;
:
procedure DisplaySelect;
This procedure parses the data buffer and displays
rows fetched. For each column in each row of the
query result, various fields in the format array
are used to identify where data values are located
in the data buffer as well as the data type of
these values and null value information.
Techniques for parsing the data buffer and more examples of dynamic
preprocessing are in the chapter, "Using Dynamic Operations."
MPE/iX 5.0 Documentation