Back to Contents


Exceptions

Summary:

See also: Flow Control, Fgl Errors.


Definition

Purpose:

In case of the abnormal execution of an instruction, the runtime system throws exceptions that can be handled by the program. Actions can be taken based on the class of the exception. There is no way to raise exceptions explicitly; only the runtime system can throw exceptions.

The WHENEVER instruction defines exception handling in a program module, by associating an exception class to an exception action.

Syntax:

WHENEVER [ANY] ERROR { CONTINUE | STOP | CALL function | GOTO label }

Notes:

  1. function can be any function name defined in the program.
  2. label can be any label defined in the current module.
  3. Exception classes ERROR and SQLERROR are synonyms (compatibility issue).
  4. Actions for classes ERROR, WARNING and NOT FOUND can be set independently.

Tips:

  1. For SQL instructions that can potentially generate errors, it is recommended that you define an exception handler locally; errors in the rest of the program can be handled by the default exception handler. See example 2 for more details.

Warnings:

  1. The scope of a WHENEVER instruction is similar to a C pre-processor macro. It is local to the module and valid until the end of the module, unless a new WHENEVER instruction is encountered by the compiler.

Trace

Exceptions will be automatically logged in a file by the runtime system if all the following conditions are true: Each log entry contains:

Exception Actions

There are four actions that can be executed if an exception is raised:

STOP
The program is immediately terminated. A message is displayed to the standard error with the location of the related statement, the error number, and the details of the exception.
CONTINUE
The program continues normally (the exception is ignored).
CALL name
The function name is called by the runtime system. The function can be defined in any module, and must have zero parameters and zero return values. The STATUS variable will be set to the corresponding error number.
GOTO name
The program execution continues at the label identified by name.

Exception Types

There are four types of exceptions, defining the kind of errors that can occur:

Type Reason Examples
ET_STATEMENT Error occurred in a statement. DISPLAY AT invalid coordinates.
ET_EXPRESSION Expression evaluation error. Division by zero.
ET_NOTFOUND An SQL statement returns status NOTFOUND. FETCH when cursor is on last row. 
ET_WARNING An SQL statement sets sqlca.sqlawarn flag. Fetched CHAR value has been truncated.

Exception Classes

The exception classes indirectly define the exception type:

Class Related Exception Type (defines the error reason) Default Action
ERROR ET_STATEMENT STOP
ANY ERROR ET_STATEMENT and ET_EXPRESSION CONTINUE
NOT FOUND ET_NOTFOUND CONTINUE
WARNING ET_WARNING CONTINUE

SQL Errors

After executing an SQL statement, you can query STATUS, SQLSTATE, SQLERRMESSAGE and the SQLCA record to get the description of the error. When the statement has been executed with errors, STATUS and SQLCA.SQLCODE contain the SQL Error Code. If no error occurs, STATUS and SQLCA.SQLCODE are set to zero.

You control the result of an SQL statement execution by using the WHENEVER ERROR exception handler:

01 MAIN
02
03   DATABASE stores
04
05   WHENEVER ERROR CONTINUE
06   SELECT COUNT(*) FROM customer
07   IF sqlca.sqlcode THEN
08      ERROR "SQL Error occurred:", sqlca.sqlcode
09   END IF
10   WHENEVER ERROR STOP
11
12 END MAIN

The SQL Error Codes are not standard. For example, ORACLE returns 903 when a table name does not exist.

By convention, the STATUS and SQLCA.SQLCODE variables always use IBM Informix SQL Error Codes. When using IBM Informix, both  STATUS and SQLCA.SQLCODE variables contain the native Informix error code. When using other database servers, the database interface automatically converts native SQL Error Codes to IBM Informix Error Codes. If no equivalent Informix Error Code can be found, the interface returns -6372 in SQLCA.SQLCODE.

If an SQL error occurs when using IBM Informix, the SQLCA variable is filled with standard information as described in the Informix documentation. When using other database servers, the native SQL Error Code is available in the SQLCA.SQLERRD[2] register. SQL Error Codes in SQLCA.SQLERRD[2] are always negative, even if the database server defines positives SQL Error Codes. Additionally, if the target database API supports ANSI SQL states, the SQLSTATE code is returned in SQLCA.SQLERRM.

The NOTFOUND (100) execution status is returned after a FETCH, when no rows are found.

See also: Connections.


Examples

Example 1:

01 MAIN
02   WHENEVER ERROR CALL error_handler
03   DATABASE stores
04   SELECT dummy FROM systables WHERE tabid=1
05 END MAIN
06
07 FUNCTION error_handler()
08   DISPLAY "Error:", STATUS
09   EXIT PROGRAM 1
10 END FUNCTION

Example 2:

01 MAIN
02   DEFINE tabname VARCHAR(50)
03   DEFINE rowcount INTEGER
04
05   # In the DATABASE statement, no error should occur.
06   DATABASE stores
07
08   # But in the next procedure, user may enter a wrong table.
09   WHENEVER ERROR CONTINUE
10   PROMPT "Enter a table name:" FOR tabname
11   LET sqlstmt = "SELECT COUNT(*) FROM " || tabname
12   PREPARE s FROM sqlstmt
13   IF sqlca.sqlcode THEN
14      ERROR "SQL Error occurred:", sqlca.sqlcode
15   END IF
16   EXECUTE s INTO rowcount
17   IF sqlca.sqlcode THEN
18      ERROR "SQL Error occurred:", sqlca.sqlcode
19   END IF
20   WHENEVER ERROR STOP
21
22 END MAIN