|
  
3
ESQL Syntax
3.1
Static ESQL with Dynamic ESQL syntax
3.2
Static ESQL
3.3
Variables
3.4
Include Variables
3.
ESQL Syntax
The ESQL/C
preprocessor will preprocess all statements that are prefixed by "EXEC
SQL"
or "$"
in an ESQL source program. An SQL statement can be placed in a C application
program anywhere a C statement is valid. However, the ESQL preprocessor
can't handle the EXEC SQL statement in a macro definition, and the ESQL/C
pre-processor will not preprocess any EXEC SQL statement in the header
files. An SQL statement must be preceded by "EXEC SQL" or
"$",
and both keywords must be placed on the same line. An SQL statement
must end with a semicolon (;).
For example:
if (c1 > 0) EXEC SQL COMMIT WORK;
3.1
Static ESQL with Dynamic ESQL syntax
According
to whether the SQL statement is known or unknown at the time of writing
and preprocessing the ESQL program, the ESQL syntax can be divided into
two types, static ESQL and dynamic ESQL.
For example,
the application can use static ESQL syntax when the complete SQL statement
is known at preprocessing time. In other words, when doing a delete/insert/update/select
operation, and the referenced table and search condition are already
known, only the input parameter value may be changed at execution time.
For this kind of syntax, DBMaker will check security and compile it
into an execution plan and then store the plan in the database. You
can reference Chapter 9, "Security",
for information about how to manage the stored information in the database.
Here is
a sample of a static ESQL/C program:
EXEC SQL INCLUDE DBENVCA;
EXEC SQL INCLUDE SQLCA;
main ( )
{
EXEC SQL BEGIN DECLARE SECTION;
int emp_id;
char emp_name[20], emp_addr[50];
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO testdb john johnspwd;
/* get user input for host var */
user_input(&emp_id, emp_name, emp_addr);
EXEC SQL INSERT INTO emp_table VALUES (:emp_id, :emp_name, :emp_addr);
EXEC SQL DISCONNECT;
}
Note:
When a host variable is referenced in a general C statement, the method
is the same as for other C variables. But when the host variable is
referenced in an EXEC SQL statement, it must start with a colon (:).
The application
can use dynamic ESQL syntax when the complete or partial SQL statement
is unknown at preprocessing time, such as when the SQL statement is
input by user input (e.g. dmsqlc) or the whole SQL statement is composed
by the query tool (QBE). For this dynamic ESQL syntax, DBMaker will
not be able to compile the SQL syntax at preprocessing time, so all
the compile and check security operations are executed at run time.
Detailed
dynamic ESQL syntax will be illustrated in Chapter 8, "Dynamic
ESQL".Here
is a sample of a dynamic ESQL/C program:
EXEC SQL INCLUDE DBENVCA;
EXEC SQL INCLUDE SQLCA;
main ( )
{
EXEC SQL BEGIN DECLARE SECTION;
char sql_string[255];
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO testdb john johnspwd;
/* get user input for SQL statement */
user_input(sql_string);
/* Dynamic ESQL statement without host variable */
EXEC SQL PREPARE statement_name FROM :sql_string;
EXEC SQL EXECUTE statement_name;
EXEC SQL DISCONNECT;
}
3.2
Static ESQL
The valid
static ESQL syntax is listed as follows:
EXEC SQL CONNECT TO database_name user_name password
EXEC SQL DISCONNECT [database_name]
- EXEC SQL INCLUDE {DBENVCA | SQLCA | SQLDA}
- EXEC SQL WHENEVER {SQLERROR | SQLWARNING | NOT FOUND}
{CONTINUE| STOP | GO TO label| GOTO label | DO action}
- EXEC SQL BEGIN DECLARE SECTION, EXEC SQL END DECLARE SECTION
- EXEC SQL [AT DATABASE_NAME] any SQL statement
- EXEC SQL [AT DATABASE_NAME] DECLARE cursor_name CURSOR FOR sql_query_statement
- EXEC SQL [AT DATABASE_NAME] OPEN cursor_name [USING host_variable_[indicator]_list]
- EXEC SQL [AT DATABASE_NAME] FETCH cursor_name [INTO host_variable_[indicator]_list]
- EXEC SQL [AT DATABASE_NAME] CLOSE cursor_name
3.3
Variables
You can
use variables from the host program in ESQL statements. In this case
they are called host variables and they pass data between the C application
and the DBMaker database. A host variable is always accompanied by another
variable called an indicator variable. While the host variable holds
a value, the indicator variable registers the special nature of that
value (if it is NULL or has been truncated).
Declare
Section
Any host
variable and indicator variable that have been referenced in EXEC SQL
statements must be declared in the declare section. The declare section
is made up of C variable declarations contained within the EXEC SQL
statements BEGIN DECLARE SECTION and END DECLARE SECTION.
For example:
EXEC SQL BEGIN DECLARE SECTION;
varchar hoEmpNo[8]; /* A host variable */
int inEmpNo; /* An indicator variable */
EXEC SQL END DECLARE SECTION;
There
can be any number of declare sections within an application program.
Every function should have its own declare section if it has host variables
and indicator variables referenced in the EXEC SQL statement. DBMaker's
dmppcc will return an error if the host variable and indicator
variable cannot be found in the declare section.
Host
Variable Data Types
You can
declare a host variable as a singleton C variable. C structures and
unions are not allowed in a host variable. Except for one-dimensional
character arrays are
used for specify char buffer length, fileobj data type cannot be used
for specifying one-dimensional array, other types of C arrays can be
declared as one dimensional array, for fetching a row set with more
than one data value in a single FETCH statement. For CHAR or BINARY
type, user can use two dimensional array to retrieve more than one data
value in a single FETCH statement.
All available
ESQL type are defined in esqltype.h.
|
ESQL/C
type
|
Type
Definition
|
Definition
|
|
char var_name[n]
|
char[n]
|
fix
length char
input (n) char
output (n-1) char+ NULL terminate
|
|
binary var_name[n]
|
char[n]
|
fix
length binary
input (n) char
output (n) char
|
|
short
|
short
|
short
integer
|
|
int
|
int
|
integer
|
|
long
|
long
|
long
integer
|
|
float
|
float
|
float
|
|
double
|
double
|
double
|
In addition
to the above data types, you can use the following SQL data types in
the declare section:
|
ESQL/C
Type
|
Type
Definition
|
Definition
|
|
date
|
typedef struct date_s {
short year;
unsigned short month;
unsigned short day;
} eq_date;
|
Date
|
|
time
|
typedef
struct time_s {
unsigned short hour;
unsigned short minute;
unsigned short second;
} eq_time;
|
Time
|
|
timestamp
|
typedef
struct timestamp_s { short year;
unsigned short month;
unsigned short day;
unsigned short hour;
unsigned short minute;
unsigned short second;
unsigned long fraction;
} eq_timestamp;
|
Timestamp
|
|
ESQL/C Type
|
Type Definition
|
Definition
|
|
varchar
var_name[n]
|
typedef
struct varchar_s {
long len;
char arr[n];
} varchar;
|
Variable
length char.
Input: Null terminated string if user has not specified len.
Output: (n-1) char +Null terminated.
|
|
varcptr
var_name[n]
|
typedef
struct varcptr_s
{
long len;
char *arr;
} varcptr;
|
Variable length char, user must assign the len value.
Input/output same as varchar
|
|
varbinary
var_name[n]
|
typedef
struct
varbinary_s
{
long len;
char arr[n];
} varbinary;
|
Variable
length binary, user must assign the len value.
Input/output same as binary.
|
|
varbptr
|
typedef
struct varbpr_s
{
long len; /* must assign a buffer length */
char *arr; /* must assign a valid buffer ptr address */
} varbptr;
|
Variable
length binary
Input/output: same as varbinary
|
BLOB data
type.
|
ESQL/C
Type
|
Type
Definition
|
Definition
|
|
Longvarchar
|
typedef
struct longvarchar_s
{
long bufsize;
char *buf;
} longvarchar;
|
BLOB
(text data)
|
|
Longvarbinary
|
typedef
struct longvarbinary_s {
long bufsize;
char *buf;
} longvarbinary;
|
BLOB
(binary data)
|
|
fileobj
|
typedef
struct fileobj_s {
long type;
char fname[MAX_FNAME_LEN];
} fileobj;
|
BLOB
(file object)
Default type is ESQL_STORE_FILE_CONTENT. You can also set type
as ESQL_STORE_FILE_NAME to store only file name on server.
|
The type
varchar is a null terminated
variable
length character string , and varbinary is a variable length binary
string without null terminate. You can vary the input or output variable's
length by assign actual length in the varchar or varbinary type's len
field. Because the actual buffer length and buffer address is not defined
for varcptr or varbptr type, you must remember to assign it prior using
it in the program.
For these
non-standard C data types, dmppcc converts them into C structures
that are recognized by the C compiler. For example, varchar is resolved
into a C structure having two elements: a length field and a character
array. .
About
fileobj's type: if you don't set the file type, the default type is
ESQL_STORE_FILE_CONTENT, which means the database server will store
user specified file's content into database, which means the file has
been copied into the database. It won't matter if the file has been
deleted after you insert this file. However, if you set file type =
ESQL_STORE_FILE_NAME, the database will only store the file name you
specified in the fname field.
Because
the database will only store the file name, you must make sure the file
is accessible by DBMaker's database server, and once you delete the
file, DBMaker will return error when you reference the file. The setting
of file type only work when using fileobj type as input parameter. As
output parameter, the database will always try to copy the data into
the filename you specified.
Example:
Use fileobj type as input host variable.
EXEC SQL BEGIN DECLARE SECTION;
fileobj fname1;
EXEC SQL END DECLARE SECTION;
EXEC SQL CREATE TABLE t1 (c1 file);
strcpy(fname1.name , "u:\image_path\test1.gif";
/* This INSERT statement will store all the content of file test.gif into database */
EXEC SQL INSERT INTO t1 VALUES (:fname1);
/* If you only want to save some database storage, and the file is located at where DBMaker
server can access network directories. You should assign the type as ESQL_STORE_FILE_NAME,
you can switch it back to store file content by assign the type to ESQL_STORE_FILE_CONTENT */
fname1.type = ESQL_STORE_FILE_NAME;
strcpy(fname1.name , "u:\image_path\test2.gif";
EXEC SQL INSERT INTO t1 VALUES (:fname1);
Example:
Use fileobj type as output variable. The schema for table t2 is c1 long
varchar.
EXEC SQL BEGIN DECLARE SECTION;
fileobj fname1;
EXEC SQL END DECLARE SECTION;
strcpy(fname1.name , "u:\image_path\test1.gif";
/* This SELECT statement will fetch the blob data from server site and put into user's local file. */
strcpy(fname1.name , "u:\local_path\test1.gif";
EXEC SQL select c1 from t2 into :fname1;
Another
example: Use fileobj as output variable with cursor:
EXEC SQL BEGIN DECLARE SECTION;
fileobj fname1;
EXEC SQL END DECLARE SECTION;
int idx1=0;
strcpy(fname1.name , "u:\image_path\test1.gif";
EXEC SQL DECLARE myCur1 CURSOR FOR select c1 from t2 into :fname1;
While (1)
{
idx1++;
/* This FETCH statement will fetch the blob data from server site and put into
user's local file. If you do not change output file name, in next FETCH statement,
the output file will be overwritten. */
sprintf(fname1.name , "test%d.gif", idx1);
EXEC SQL FETCH myCur1;
if (SQLCODE)
{ /* Break while loop when no more data or there's error */
if (SQLCODE != SQL_SUCCESS_WITH_INFO)
break;
}
}
Host
Variables
You must
apply the following rules when using host variables in a C application
program:
- The
host variables must be declared according to the regular syntax of
the host language (the C language) and DBMaker's ESQL supported data
types as defined in this guide.
- The
number of host variables in the INTO clause is equal to or less than
the number of columns named in the SELECT statement., and the data
type of input or output host variable must be a compatible data type
with the corresponding parameter or projection column.
For example:
EXEC SQL BEGIN DECLARE SECTION;
char emp_id[20]; /* employee ID */
char emp_tel[20]; /* employee telephone # */
int indvalue = SQL_NTS
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT emp_id, emp_tel FROM emp_tab INTO :emp_id :indvalue,
:emp_tel :indvalue
- The
host variables must be compatible with column value types.
- The
host variables must always be prefixed by a colon (:) in SQL statements;
when used elsewhere in an application program, no colon is necessary.
For example:
EXEC SQL BEGIN DECLARE SECTION;
char emp_id[20]; /* employee ID */
char emp_tel[20]; /* employee telephone # */
int indvalue = SQL_NTS; /* indicates input parameter is null terminated */
EXEC SQL END DECLARE SECTION;
strcpy(emp_id, "john Smith");
strcpy(emp_tel, "765-4321");
EXEC SQL INSERT INTO emp_tab VALUES (:emp_id :indvalue, :emp_tel :indvalue);
Once host
variables are established, the data can be retrieved into the variable
by DBMaker for use by the application program. A host variable can also
be used to insert and update data, or in the WHERE and HAVING clauses.
In the
following example, the host variable hoDeptNo is an output host variable
that receives the output. The host variable hoEmpNo is an input host
variable that has been initialized with the code for select criteria.
EXEC SQL BEGIN DECLARE SECTION;
int hoDeptNo, hoEmpNo;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT deptNo FROM Employee WHERE empNo = :hoEmpNo INTO :hoDeptNo;
Variable
Scope
You can
declare the variable scope as EXTERN or STATIC in the declare section
in the same way as other C variables.
- External
global variable
When
you want to reference an external variable, whose data type is the
same as one of ESQL's supported data types, you can add æ'XTERN"
in front of the ESQL variable declaration.
For
example:
EXEC SQL BEGIN DECLARE SECTION;
extern int var1;
EXEC SQL END DECLARE SECTION;
Static
variable
When
you want to set the local variable as a static variable, you can add
"STATIC" in front of the ESQL variable declaration.
For
example:
EXEC SQL BEGIN DECLARE SECTION;
static int var1;
EXEC SQL END DECLARE SECTION;
Variable
passed in function
When
you want to reference the value from this function's input variable,
or return the value gotten from an ESQL SQL query statement, you must
copy the variable data or reassign the pointer to the ESQL variable's
data structure.
For
example:
/* Method 1, copy the value to esql host variable */
func1(int input_emp_id, char *output_telno)
{
EXEC SQL BEGIN DECLARE SECTION;
int emp_id;
char telno[15];
EXEC SQL END DECLARE SECTION;
emp_id = input_emp_id; /* copy the input value */
EXEC SQL SELECT telno FROM emp_tab WHERE emp_id = :emp_id INTO :telno;
strcpy(output_telno, telno);
}
/* Method 2, reassign the buffer pointer */
func1(char *input_emp_name, char *output_telno)
{
EXEC SQL BEGIN DECLARE SECTION;
varcptr p_name, p_telno;
EXEC SQL END DECLARE SECTION;
p_name.len = strlen(input_emp_name); /* input string length */
p_name.arr = input_emp_name;
p_telno.len = 15; /* output string length */
p_telno.arr = output_telno;
EXEC SQL SELECT telno FROM emp_tab WHERE emp_name = :p_name INTO :p_telno;
}
Indicator
Variables
Indicator
variables are an optional means to handle null values and truncation
for host variables in the application program. When an indicator variable
is used, it follows a host variable in the SQL statements. Declare indicator
variables as integers only.
For example:
EXEC SQL BEGIN DECLARE SECTION;
int hoDeptNo, indDeptNo, hoEmpNo;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT deptNo FROM Employee
WHERE empNo = :hoEmpNo
INTO :hoDeptNo :indDeptNo;
In the
above example, the indicator variable indDeptNo immediately follows
the host variable hoDeptNo and is prefixed with a colon. The values
in an indicator variable are:
|
Indicator
Value
|
Value
Retrieved From the Database
|
|
SQL_NULL_DATA
|
NULL
value returned; output host variable is indeterminate.
|
|
0
or greater
|
The
indicator variable will be set as the
original
output host variable buffer length. If
the indicator variable is for getting blob data, the indicator
value set to the original output host variable buffer length in
the database prior getting the blob data.
|
To use
an indicator variable to input a NULL value into the database, the corresponding
host variable is ignored.
For example:
EXEC SQL BEGIN DECLARE SECTION;
int hoDeptNo, indDeptNo;
EXEC SQL END DECLARE SECTION;
inDeptNo = SQL_NULL_DATA;
EXEC SQL INSERT INTO Department (DeptName, DeptNo)
VALUES ('Human Resource', :hoDeptNo :inDeptNo);
The above
example will insert the NULL value into the DeptNo column, and the value
of hoDeptNo will be ignored.
|
Indicator
Value
|
Value
Accepted Into the Database
|
|
SQL_NULL_DATA
|
NULL
value.
|
|
0
or greater
|
Actual
buffer length of input host variable, for CHAR and BINARY types.
When an indicator variable is provided, the host variable length
set in VARCHAR/VARBINARY data types is ignored.
|
|
SQL_NTS
|
Buffer
is null terminated for CHAR and BINARY data types. The host variable
length set in VARCHAR/VARBINARY data types is ignored.
|
Include
Variables
There are
three kinds of declarations for special data structures required by
DBMaker's preprocessor or the runtime application: they are dbenvca,
sqlca, and sqlda.
The dbenvca
declaration is an environment variable DBMaker uses in your application
program. You must declare it in the program.
The syntax
is:
EXEC SQL INCLUDE [EXTERN] dbenvca;
For example:
file1.c
EXEC SQL INCLUDE DBENVCA;
main()
{
...
EXEC SQL .
...
}
file2.c
EXEC SQL INCLUDE EXTERN DBENVCA;
func1()
{
...
}
The syntax
for declaring sqlca and sqlda are same as for dbenvca. Sqlca is used
to communicate the status code and sqlda is used in dynamic ESQL. Both
are discussed in detail later.
   
|