The Scope of Variables
The preprocessor references all variables declared in an embedded SQL declaration section and accepts them from the point of declaration to the end of the file. This may not be true for the C compiler, which only allows variables to be referred to in the scope of the nearest enclosing program block in which they were declared. If you have two unrelated procedures in the same file, each of which contains a variable with the same name to be used by embedded SQL, you do not have to redeclare the variable in a declaration section. The preprocessor uses the data type information supplied by the first declaration.
If you do redeclare the variable, the preprocessor confirms that both declarations have compatible data types and the same indirection level. The indirection level is the sum of the number of pointer operators preceding the variable declaration name and the number of array dimensions following the name. This redeclaration can only occur for simple, non-structured variable or formal procedure parameter declarations. Do not redeclare structures, typedefs, enumerated types and arrays even if used in a different context.
If you declare a variable name in two incompatible instances, the preprocessor generates an error and continues to process any references to the variable using only its first declaration. You can solve the problem by renaming the variables declared in the second and any subsequent declarations.
In the following program fragment, the variable dbname is passed as a parameter between two procedures. In the first declaration section, the variable is a local variable. In the second declaration section, the variable is a formal parameter passed as a string to be used with the connect statement. In both cases, the data type attributes are compatible character strings.
Example: Variable declaration
exec sql include sqlca;
Access_Db()
{
exec sql begin declare section;
char dbname[20];
exec sql end declare section;
/* Prompt for and read database name */
printf("Database: ");
gets(dbname);
Open_Db(dbname);
...
}
Open_Db(dbname)
exec sql begin declare section;
char *dbname;
exec sql end declare section;
{
exec sql whenever sqlerror stop;
exec sql connect :dbname;
...
}
The previous example is the first to demonstrate a formal parameter to a procedure in a declaration section. In this particular example, you do not need to declare the parameter, in which case the preprocessor uses the character string data type of the initial declaration of dbname. For example:
Open_Db(dbname)
char *dbname;
{
exec sql whenever sqlerror stop;
exec sql connect :dbname;
...
}
To enhance the readability of the examples in this document, formal parameters are not declared. Instead, local variables are declared that can be initialized to formal parameters.
For example, the Open_Db procedure above could also be written as:
Open_Db(dbname)
char *dbname;
{
exec sql begin declare section;
char *dbnm = dbname;
exec sql end declare section;
exec sql whenever sqlerror stop;
exec sql connect :dbnm;
...
}
Be careful when using variables in a declare cursor statement. The variables used in such a statement must also be valid in the scope of the open statement for that same cursor. The preprocessor actually generates the code for the declare at the point that the open is issued and, at that time, evaluates any associated variables. For example, in the following program fragment, even though the variable number is valid to the preprocessor at the point of both the declare cursor and open statements, it is not a valid variable name for the C compiler at the point that the open is issued.
Init_Csr1() /* This example contains an error */
{
exec sql begin declare section;
int number; /* A local variable */
exec sql end declare section;
exec sql declare cursor1 cursor for
select ename, age
from employee
where eno = :number;
/* Initialize "number" to a particular value */
...
}
Process_Csr1()
{
exec sql begin declare section;
char ename[16];
int age;
exec sql end declare section;
exec sql open cursor1; /* Illegal evaluation of
"number" */
exec sql fetch cursor1 into :ename, :age;
...
}