All statements in your C program, including SQL statements, must be contained in columns 1 through 72 of your source file. Columns 73 through 80 can also be used if the NOSEQuence C preprocessor option is specified; if NOSEQuence is not specified, or if SEQuence is specified, these columns will be ignored by the preprocessor. If NOSEQuence is used, the NOSEQ and MARGINS(1,80) C compiler options must be used to compile the application program.
In a VSE environment, C comments may not start at column 1 because a "/*" starting at column 1 will be mistaken as an End-Of-Data-File JCL command. Other VSE restrictions may apply to the use of column 1 in C application programs.
Continuation of SQL statements and host variable declare statements across lines can be accomplished by breaking the line anywhere a blank can occur. Continuation of tokens (the basic syntactical units of a language) is allowed from one line to the next, by coding a backslash (the C continuation character with hex value X'E0') in the line to be continued immediately after the first part of the token (leaving the remainder of the line blank), and coding the next part of the token from column 1 on the continuation line. If column 1 on the continuation line is blank, the token is not continued. See the DB2 Server for VSE & VM SQL Reference manual for a discussion of tokens.
You can also use the trigraph ??/ in place of the backslash as the continuation character. The C preprocessor treats end-of-line like a blank delimiter except when it is in a literal.
Use delimiters on all SQL statements to distinguish them from regular C statements. You must begin each SQL statement in your program with EXEC SQL, and end each statement with a semicolon. EXEC and SQL must be in uppercase on the same line, with only blanks separating them (no in-line C or SQL comments). Also, EXEC SQL must be immediately followed by a blank, C comment, or SQL comment, and it must be preceded by either a blank, C comment, {, }, trigraph ??<, trigraph ??>, ), colon, or semicolon.
Elsewhere within SQL statements, C and SQL comments are allowed anywhere that blanks are allowed. However, there must not be any comments within SQL statements that are dynamically defined and executed.
Any SQL statement except INCLUDE can be followed on the same line by another SQL statement, C statement, or C comment.
The keywords EXEC SQL must appear in uppercase in your C program. The rest of an SQL statement can appear in mixed case, but will be interpreted as uppercase, except for host variable names and text within quotation marks, which will be left in the original case.
Note: | C host variables are always treated with case sensitivity by the C preprocessor. This is true for the C compiler too, except for externals, which C may truncate and fold to uppercase. Keep this in mind when using host variables with external scope. |
Remember to follow SQL, not C, conventions when coding such character constant strings. These strings must be delimited by single quotation marks, and an embedded backslash is not recognized as an escape character.
To include external secondary input, specify:
EXEC SQL INCLUDE text_name
at the point in the source code where the secondary input is to be included.
DB2 Server for VM |
---|
The text_name is the file name of a CMS file with a "CCOPY" file type and located on a CMS minidisk accessed by the user. It is always folded to uppercase. If anything is found after an INCLUDE statement, a warning message is issued and the input is ignored. |
DB2 Server for VSE |
---|
The text_name is the member name of a "B" type source member of a VSE library. |
Use the SQL INCLUDE statement instead of the C preprocessor #include directive to include files that contain SQL host variables or SQL statements.
The CONNECT statement is required to establish a connection between the database manager and the program. To do an explicit connect, specify:
EXEC SQL CONNECT :userid IDENTIFIED BY :password;
Both userid and password must be host variables declared as fixed length 8 character strings.
The preprocessor must run before the C compiler and its built-in preprocessor. It is therefore not possible to contain any C preprocessor directives within an SQL statement. The SQL INCLUDE statement should be used instead of the C #include for files that contain SQL host variable declarations or statements.
You must declare all host variables in an SQL declare section. For a description of an SQL declare section, refer to Declaring Variables That Interact with the Database Manager.
Declare host variables in the source file before the first use of the variable in an SQL statement. You can use the following types of variables in an SQL statement:
Scalar variables, structure elements, and array elements are data objects. For information on the use of these variables in an SQL statement, refer to "Using Host Variables" and "Using Host Structures".
Note: | You can declare non-host variables in an SQL declare section; however, declarations that do not conform to DB2 Server for VSE & VM declaration rules may return errors. |
The definition of a host variable is subject to the following rules:
The keyword int is optional in the declaration of a short or long integer. You cannot use the unqualified type int when declaring a variable to be used in an SQL statement: specify short or long.
You can use the unsigned qualifier with character array host variables. It does not affect the way the system treats them.
An explicit constant decimal array size is required between the brackets, even if an initializer is used on the declare. Expressions, preprocessor functions (such as sizeof), octal or hex values, and #defined variables cannot be used as the size of character arrays.
short ind_array [10];
You cannot use indicator array elements as main or indicator variables.
struct tag { short vlen; char vstr[nnn]; } varname1;
The structure tag is optional. Any legal C names can be used for the structure and the contained variables. The nnn, defining the length of the largest string to be held in the structure, is specified by you.
This structure defines a VARCHAR or LONG VARCHAR host variable with the name varnamel and a length nnn You cannot use this structure as a host structure; you cannot use the elements of the structure as host variables.
The system does not add or expect a NUL at the end of a VARCHAR or LONG VARCHAR string. If one is needed, you can use a character array host variable, or you can add one after the data value has been returned, with the statement:
varname1.vstr[varname1.vlen]='/0';
If a NUL is required, ensure that the nnn is one larger than the maximum allowable string, so that adding the NUL at the end will never overflow the allocated storage.
A macro is provided to assist in the declaration of VARCHAR structures:
SQLVARCHAR(varname,nnn) will expand to: struct{ short sqllen; char sqlstr[nnn]; }varname;
You can use this macro wherever a structure declaration defines a varying-length string.
struct tag{char projno [7]; short actno; long acstaff; char acstdate [10]; char acendate [10]; }projstrct;
Note: | The structure tag is optional. |
This structure represents the following list of host variables when used in an SQL statement:
projno, actno, acstaff, acstdate, acendate
In other words, the two following SQL statements are equivalent:
EXEC SQL SELECT PROJNO, ACTNO, ACTSTAFF, ACSTDATE, ACENDATE INTO :projstrct FROM PROJ_ACT WHERE PROJNO = '100000'
EXEC SQL SELECT PROJNO, ACTNO, ACSTAFF, ACSTDATE, ACENDATE INTO :projno, :actno, :acstaff, :acstdate, :acendate FROM PROJ_ACT WHERE PROJNO = '100000'
A host structure can either be a stand-alone structure or a substructure of a more complex structure. The following example is a complex structure that contains a host structure:
struct tag { char empno [7]; struct taga { char firstname [13]; char midinit [1]; char lastname [16]; } empname; char workdept [3]; char phoneno [4]; } employee;
The structure empname is a host structure.
You can use the elements of the host structure and the elements of a complex structure containing a host structure as host variables. In the previous example, you can use empno, firstname, midinit, lastname, workdept and phoneno as host variables.
You can code a substructure in the host structure to represent a varying-length string element if the substructure conforms to the rules for a varying-length string definition. All of the rules in the description of structures that define varying-length strings also apply in this situation. The following example is a host structure that contains a VARCHAR element:
struct tag { struct taga { short fnlen; char fntext [12]; } firstname; char midinit [1]; struct tagb {short 1nlen; char 1ntext [15]; } lastname; } empname;
The C preprocessor interprets the structure empname as a host structure containing 3 elements: firstname with data type VARCHAR and length 12, midinit with data type CHAR and length 1, and lastname with data type VARCHAR, and length 15.
Note: | Any structure matching the description of a varying-length string definition is interpreted as a VARCHAR or LONG VARCHAR variable and cannot be used as a host structure. |
EXEC SQL BEGIN DECLARE SECTION; struct { char last??(9??); char first??(9??); struct { short addlen; char addtext??(200??); } address; } empname; EXEC SQL END DECLARE SECTION; main() { EXEC SQL SELECT LASTNAME, FIRSTNME, ADDRESS INTO :empname FROM EMPLOYEE WHERE LASTNAME = 'JOHANSON'; }
In this example, empname is considered by the C preprocessor to be a two-level structure because the structure of address matches that of a VARCHAR data type. As a result, empname may be used in the SELECT statement. If, for example, addlen was changed from short to long, the structure of address would no longer match a VARCHAR data type and empname would be considered a three-level structure. As a result, empname could NOT be used in a SELECT statement.
static short partno, suppno, time; static char name [16] , adr[36]; static double qonhand, qonorder, price;
Note: | You must explicitly declare all structures in C within the multi-level
structure. You cannot declare a structure for reference within another
structure (except for the SQLVARCHAR macro). In the following example,
only dates and product may be used as host
structures. orderno and custnum may be used as
scalar host variables and may be qualified as
custord.orderno and ordinfo.custnum or
custord.ordinfo.custnum.
EXEC SQL BEGIN DECLARE SECTION; struct { char orderno??(10??); struct { char custnum??(10??); struct { char ordate??(7??); char delivdte??(7??); } dates; } ordinfo; struct { char stockno??(11??); char quantity??(4??); } product ; } custord ; EXEC SQL END DECLARE SECTION; main() { EXEC SQL SELECT STOCKNO, QUANTITY INTO :product FROM ORDER WHERE STOCKNO = '1234567890'; } |
Note: | Because of the restriction on the number of host variables in a statement, host structures with greater than 256 fields will not be allowed, |
Note that other program variables can also be declared as usual outside the SQL declare section. The previous restrictions do not apply to non-SQL declarations.
When you reference host variables, host structures, structure fields or indicator arrays in an SQL statement, you must precede each reference by a colon (:) The colon distinguishes these variables from SQL identifiers (such as column names). The colon is not required outside an SQL statement.
Scalar host variables can be defined as pointers to any C data type that the database manager supports. The following rules and restrictions apply:
short *partno; ... SELECT PARTNO INTO :*partno ...
The use of parentheses is required in order for arrays to define a pointer to an array of 5 characters, as opposed to an array of 5 pointers to characters. (See Using C NUL-Terminated Strings and Truncation for the limitations on string lengths.)
The host variable would then be referenced as *v1_ptr in an SQL statement.
There are primarily two uses for pointer types with SQL statements:
A program could contain a single SQL declare section, and use pointers for some or all large data areas. Then, before a pointer is used in an SQL statement, an alloc function could be used to acquire storage and set the pointer, or the pointer could be set to a shared storage area. This allows the program to reduce its overall storage requirement. For example:
EXEC SQL BEGIN DECLARE SECTION; ... struct tag { short vlen; char vstr[1000]; } *vstr_ptr; ... EXEC SQL END DECLARE SECTION; ... vstr_ptr = (struct tag *) malloc(sizeof(struct tag)); EXEC SQL SELECT DESCRIPTION INTO :*vstr_ptr FROM TABLE; ... }
C usually passes parameters by value. This prevents the called function from changing the caller's version of a parameter. Passing a parameter by reference can be accomplished by the caller explicitly passing a pointer to the data. The called function then changes the data referenced by the pointer by using the asterisk for indirection. If the value is to be changed with an SQL statement, the called function must also declare the pointer value of the parameter in an SQL DECLARE section. For example:
main() { EXEC SQL BEGIN DECLARE SECTION; ... long int partno; ... EXEC SQL END DECLARE SECTION; getdata(&partno); ... } getdata(partno_ptr) EXEC SQL BEGIN DECLARE SECTION; long int *partno_ptr; EXEC SQL END DECLARE SECTION; { EXEC SQL SELECT PARTNO INTO :*partno_ptr FROM TABLE; ... }
Host variables with the same name can only be declared in one SQL declare section. When passing a host variable to a function within the same file as the calling function, the variable can be used in an SQL statement in the called function without being redeclared in an SQL declare section. For example:
main() { EXEC SQL BEGIN DECLARE SECTION; ... long int partno; ... EXEC SQL END DECLARE SECTION; getdata(partno); ... } getdata(partno) long int partno; { EXEC SQL BEGIN DECLARE SECTION; long int qonhand; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT QONHAND INTO :qonhand FROM TABLE WHERE PARTNO = :partno; ... }
Given the SQL declaration of partno within main(), partno can be used in any SQL statement that follows it in the file. If getdata had a different name for the partno parameter, it would have to be included in getdata's SQL declare section.
For information on how to allow a called function to update a parameter, refer to Using the Pointer Type Attribute.
Host variables must be type-compatible with the columns with which they are to be used. For example, if you want to retrieve into a program variable the QONHAND column of the database, and the data type of QONHAND is INTEGER, you should declare the program variable to be of type short, long, float, or double.
The database manager considers the numeric data types compatible as well as the character string data types (CHAR, VARCHAR, and LONG VARCHAR, including strings of different declared lengths). Of course, an overflow condition may result if, for example, you assign a 31-bit integer to a 15-bit integer and the current value of the 31-bit integer is too large to fit in 15 bits. Truncation also occurs when a decimal number having a scale greater than zero is assigned to an integer. In general, overflow occurs when significant digits are lost, and truncation occurs when nonsignificant digits are lost.
The system also considers the datetime data types to be compatible with character data types (CHAR, and VARCHAR, but not long fields).
The database manager interprets a character string in C as NUL-terminated if the length of the string is greater than 1 byte and less than 32,768 bytes.
The NUL-byte is mandatory when the database manager receives data from a NUL-terminated string. You receive an SQLCODE -302 (SQLSTATE '22024') if the NUL-byte is not found within the defined length of the string. This means that the maximum number of bytes of data that can be stored in a NUL-terminated string is one less than the defined length of the string.
When data is sent from the application server to a NUL-terminated string, a
NUL-byte is always appended to the end of the string. If the variable
is not big enough to hold the entire string (including the NUL), then a
warning condition is indicated using the SQLCA SQLWARN flags and the output
indicator value, as shown in the following chart. Truncation will occur
even in the case where a character value of actual length n is to be
assigned to a C variable declared as length n due to the NUL
character being inserted at the last byte of the declared length. When
truncation occurs, that last byte is overwritten by NUL.
Figure 111. Warning Flags after Character Truncation
|
SQLCA SQLWARN0 |
SQLCA SQLWARN1 |
Output Indicator Variable (if supplied) |
---|---|---|---|
Character string, including the NUL, fits in the declared C character array. | blank | blank | 0 (zero) |
Actual data truncated. That is, the C variable declared as less than or equal to n, to hold a character value of actual length n. | W | W | Original length of value (n) excluding the NUL. |
Date calculations can result in date durations, and the database manager converts the result into any numeric type of a column or a host variable. However, to involve a date duration in a calculation (for example, to add a duration to a date), the date duration must be in DECIMAL(8,0) format. The system does not automatically convert any numeric type of column or host variable to a decimal value for use in a date calculation. If your C compiler does not support the fixed decimal data format, the scalar "DECIMAL" conversion function must be used to explicitly convert a value to decimal type. For example,
long duration=10100; /* 1 year and 1 month */ long result_dt; EXEC SQL SELECT START_DATE+DECIMAL(:duration,8,0) INTO :result_dt FROM TABLE;
A trigraph is a sequence of three characters that you write in place of a C source character that your input device does not generate. The following trigraphs are supported by the C preprocessor in an SQL declare section:
??( [ (left bracket) ??) ] (right bracket) ??< { (left brace) ??> } (right brace)
The following trigraph is supported in an SQL statement only when used as a continuation character:
??/ \ (backslash)
The rules for the format and use of DBCS characters in SQL statements are the same for C as for other host languages supported by the system. For a discussion of these rules, see Using a Double-Byte Character Set (DBCS).
The C language does not provide a way to define graphic host variables. If you want to add graphic data to or retrieve it from DB2 Server for VSE & VM tables, you must execute the affected statements dynamically. By doing so, the data areas that are referenced by each statement can be described in an SQLDA. In the SQLDA, you must set the data type of the areas containing graphic data to one of the graphic data types. For a discussion of the SQLDA, refer to the DB2 Server for VSE & VM SQL Reference manual.
When preprocessing an SQL C program, every executable SQL statement is translated into control block declarations, assignment statements, and a function call to pass the control block to the preprocessor at run time. To simplify the generation of this code during preprocessing, a number of typedef and communication area definitions are placed just after any initial C compiler directives or comments.
In addition, to assist the application programmer, the SQLVARCHAR macro is inserted with the typedefs and communication area definitions.
The preprocessor-generated statements are described in Figure 112. These statements are inserted immediately before the first line in the source program that is not a blank line, a C comment, or a C precompiler directive.
The C preprocessor imposes two restrictions on the coding of C precompiler directives:
Figure 112. C Preprocessor-Generated Statements
Generated Code | Purpose |
---|---|
#pragma linkage (ARIPRDI,OS) | To establish correct addressability and parameter passing conventions with the system at run time. |
#ifndef SQLVARCHAR #define SQLVARCHAR(varname,nnn) \ struct { \ short sqllen; \ char sqlstr[nnn]; \ } varname #endif | Macro that can be used by the application to simplify the C program. The definition of this macro can be changed by including a #define statement before the first non-precompiler directive C statement or SQL statement in your program. |
typedef struct { short CALLTYPE; char AUTHOR[8]; short PROG_NAMEL; char PROG_NAME[8]; short SECTION_NUM; short CLASS_SECTION; char *CODEPTR; char *VPARAMPTR; char *AUXPARAMPTR; char *SQLTIEPTR; char SPECIALCALL; char CALLFLAG; char WAITFLAG; char RELEASEFLAG; char VPARAMIND; char AUXPARAMIND; char ERRORFLAG; char RDIDESCFLAG; long MAILBOXLEN; char RDIRELNO; char RDICISL; char RDIDATE; char RDITIME; long RDIFDBCK; char *RDIEXTP; char RDIRESV1[2]; char RDIRDB16; char RDIRESV2; } SQL_RDIIN; typedef struct { char *RDIPTR01; char *RDIPTR02; } SQL_RDIPT; typedef struct { short DATA_TYPE; short LEN; char *DATA_PTR; short *INFOPTR; short NAMEL; char NAME[30]; } SQL_PVELMS; typedef SQL_PVELMS *SQL_PVLMP; typedef struct { short CURSRLEN; char CURSRNAM[18]; } SQL_RDICURAR; typedef union { long rdicnstl[2]; char rdicnstc[8]; } SQL_RDICONST; | typedefs of allocated control blocks used when translating executable SQL statements into C function calls. |
static long SQLTIE[12]; static char RDIRDBN[16]; static struct { char RDIEXTEC[8]; long RDIEXTFLR; char *RDIDBNMP; char *RDICONSP; char *RDIBPOPT; char *RDIXPTRS[6]; } SQLRDIX; | Communication areas used to save information about the state of the C program between run-time calls to the database manager. |