informix
INFORMIX-ESQL/C Programmer's Manual
Working with the Database Server

The timeout Program

The timeout program demonstrates how to set up a time-out interval. This program uses the sqlbreakcallback() function to perform the following actions:

If execution of an SQL request exceeds the time-out interval, the callback function uses the sqldone() function to ensure that the database server is still busy, prompts the user for confirmation of the interrupt, and then uses the sqlbreak() function to send an interrupt request to the database server.

Compiling the Program

Use the following command to compile the timeout program:

The -o timeout option causes the executable program to be named timeout. Without the -o option, the name of the executable program defaults to a.out. See Using the esql Command for more information on the esql command.

Guide to the timeout.ec File

Continued on page 12-52

Lines 4 to 9

Lines 4 to 8 include the UNIX header files from the /usr/include directory. The ESQL/C sqltypes.h header file (line 9) defines names for integer values that identify SQL and C data types.

Lines 10 to 20

Line 10 defines LCASE, a macro that converts an uppercase character to a lowercase character. The DB_TIMEOUT (line 12) constant defines the number of milliseconds in the time-out interval. The SQL_INTERRUPT constant (line 13) defines the SQLCODE value that the database server returns when it interrupts an SQL statement.

Lines 17 and 18 define constants that the create_tbl() function uses to create the canceltst table. This table holds the test data needed for the large query (lines 125 to 132). MAX_ROWS is the number of rows that create_tbl() inserts into canceltst. You can change this number if you find that the query does not run long enough for you to interrupt it. CHARFLDSIZE is the number of characters in the character fields (char_fld1 and char_fld2) of canceltst.

Line 20 defines the SERVER_BUSY constant to hold the sqldone() return value that indicates that the database server is busy processing an SQL request. Use of this constant makes code more readable and removes the explicit return value from the code.

Lines 24 and 25

The exp_chk2() exception-handling function uses the WARNNOTIFY and NOWARNNOTIFY constants (lines 24 and 25). Calls to exp_chk2() specify one of these as the second argument to indicate whether the function displays SQLSTATE and SQLCODE information for warnings (WARNNOTIFY) or does not display this information for warnings (NOWARNNOTIFY). For more information on the exp_chk2() function, see Lines 348 to 355.

Lines 29 to 33

The main() program block begins on line 29. Lines 31 to 33 declare variables local to the main() program block.

Continued on page 12-54

Lines 43 to 50

The create_tbl() function creates the canceltst table in the stores7 database. It inserts MAX_ROWS number of rows into this table. If create_tbl() encounters some error while it creates canceltst, execution of the timeout program cannot continue. The program exits with a status value of 1 (line 49).

Line 51

This while loop (which ends on line 97), controls the execution of the query on the canceltst table. It allows the user to run this query multiple times to test various interrupt scenarios.

Lines 53 to 67

The first task of the while loop is to use sqlbreakcallback() to specify a time-out interval of DB_TIMEOUT (200) milliseconds and to register on_timeout() as the callback function. If this call to sqlbreakcallback() fails, the program exits with a status value of 1. To test different time-out intervals, you can change the DB_TIMEOUT constant value and recompile the timeout.ec source file.

Lines 68 to 72

These printf() functions notify the user of the time-out interval. Notice that the message displays this interval in minutes, not milliseconds. It divides the DB_TIMEOUT value by 60,000 (number of milliseconds in a minute).

Lines 73 to 83

The prompt_ans() function asks the user to indicate when to begin execution of the canceltst query. If the user enters n (no), the program calls the sqlbreakcallback() function to unregister the callback function. This call prevents the SQL statements in the drop_tbl() function (lines 322 to 329) from initiating the callback function. For a description of the prompt_ans() function, see Lines 337 to 347.

Continued on page 12-56

Lines 84 to 97

If the user chooses to continue the query, the program calls the dspquery() function (line 88) to run the canceltst query. The prompt_ans() function displays a prompt so the user can decide whether to run the program again.

Lines 98 to 101

The drop_tbl() function drops the canceltst table from the stores7 database to clean up after the program.

Lines 108 to 120

The dspquery() function runs a query of the canceltst table and displays the results. It returns zero (success) or the negative value of SQLCODE (failure) to indicate the result of the canceltst query.

Lines 121 to 132

Line 125 declares the cancel_curs cursor for the query. The actual SELECT (lines 126 to 132) obtains the sum of the int_fld column and the values of the two character columns (char_fld1 and char_fld2). The WHERE clause uses the MATCHES operator to specify matching rows, as follows:

This SELECT is artificially complex to ensure that the query takes a long time to execute. Without a reasonably complex query, the database server finishes execution before the user has a chance to interrupt it. In a production application, only use the sqlbreakcallback() feature with queries that take a long time to execute.

Continued on page 12-58

Line 133

This OPEN statement causes the database server to execute the SELECT that is associated with the cancel_curs cursor. Because the database server executes the canceltst query at this point, this OPEN is the statement that the user would be most likely to interrupt. When the FETCH executes, the database server just sends matching rows to the application, an operation that is not usually time intensive.

Lines 134 to 154

This block of code checks the success of the OPEN. Since the OPEN can be interrupted, this exception checking must include an explicit check for the interrupt value of -213. The database server sets SQLCODE to -213 when it has interrupted an SQL request. On line 140, the program uses the SQL_INTERRUPT defined constant (which line 13 defines), for this SQLCODE value.

The sqlstate_err() function (line 135) uses the GET DIAGNOSTICS statement to analyze the value of the SQLSTATE variable. If this function returns a non-zero value, SQLSTATE indicates a warning, a runtime error, or the NOT FOUND condition. Before the call to sqlstate_err(), line 134 saves the SQLCODE value so that execution of any other SQL statements (such as GET DIAGNOSTICS in sqlstate_err()) does not overwrite it. The function returns the value of SQLCODE if the OPEN encounters a runtime error (line 150).

The first if statement (line 136) checks if the OPEN encounters any type of exception (sqlstate_err() returns a nonzero value). The second if (line 138) checks if the OPEN has generated a runtime error (return value of -1). However, if the database server has interrupted the OPEN, sqlstate_err() also returns -1. Since ESQL/C does not handle an interrupted SQL statement as a runtime error, the third if checks explicitly for the SQL_INTERRUPT value (line 140). If the OPEN was interrupted, line 143 notifies the user that the interrupt request was successful and then the function resets the saved SQLCODE value (in sqlcode) to zero to indicate that the OPEN did not generate a runtime error.

Lines 146 and 147 execute only if the OPEN generates a runtime error other than SQL_INTERRUPT (-213). The disp_error() function displays the exception information in the diagnostics area and the SQLCODE value. Lines 148 to 150 clean up after the OPEN. They close and free the cancel_curs cursor and then return the SQLCODE value. The dspquery() function does not continue with the FETCH (line 158) if the OPEN was interrupted.

If sqlstate_err() returns one (1), the OPEN has generated a warning. Lines 152 and 153 call the disp_warning() function to display warning information from the diagnostics area. For more information on the disp_error() and disp_warning() functions, see Lines 341 to 348 on page 12-67.

Continued on page 12-60

Lines 155 to 182

This while loop executes for each row that the cancel_curs cursor contains. The FETCH statement (line 158) retrieves one row from the cancel_curs cursor. If the FETCH generates an error, the function releases the cursor resources and returns the SQLCODE error value (lines 176 to 181). Otherwise, the function displays the retrieved data to the user. On the last row (ret = 100), the function displays the number of rows that it retrieved (line 173).

Lines 185 to 187

After the FETCH has retrieved the last row from the cursor, the function releases resources allocated to the cancel_curs cursor and returns a success value of zero.

Lines 190 to 199

The on_timeout() function is the callback function for the timeout program. The sqlbreakcallback() call on line 62 registers this callback function and establishes a time-out interval of 200 milliseconds. This function is called every time the database server begins and ends an SQL request. For long-running requests, the application also calls on_timeout() each time the time-out interval elapses.

Continued on page 12-62

Lines 199 to 249

This switch statement uses the callback function argument, when_called, to determine the actions of the callback function, as follows:

To handle the elapsed time-out interval, the callback function first calls the ESQL/C sqldone() function (line 223) to determine whether the database server is still busy processing the SQL request. If the database server is idle, the application does not need to send an interrupt. If sqldone() returns SERVER_BUSY (-439), the database server is still busy.

Line 224 checks if the user has already attempted to interrupt the SQL request that is currently executing. If an interrupt was sent, intr_sent is 1, and the program does not need to send another request. If an interrupt request has not yet been sent, the callback function notifies the user that the time-out interval has elapsed (lines 226 to 229). It then uses the cancel_request() function (line 233) to allow the user to confirm the interrupt. For more information on cancel_request(), see Lines 251 to 261.

Continued on page 12-64

Lines 199 to 249 (continued)

If the user confirms the interrupt, the callback function calls the sqlbreak() function to send the interrupt request to the database server. The callback function does not wait for the database server to respond to the interrupt request. Execution continues to line 243 and sets the intr_sent flag to 1, to indicate that the interrupt request was sent. If the callback function was called with an invalid argument value (a value other than 0, 1, or 2), the function displays an error message (line 247).

Lines 251 to 261

The cancel_request() function asks the user to confirm the interrupt request. It displays the prompt:

If the user answers y (yes), cancel_request() returns 0. If the user answers n (no), cancel_request() returns 1.

Lines 262 to 281

The create_tbl() function creates the canceltst table and inserts the test data into this table. The CREATE TABLE statement (lines 277 and 278) creates the canceltst table with three columns: int_fld, char_fld1, and char_fld2. If the CREATE TABLE encounters an error, the exp_chk2() function (line 279) displays the diagnostics-area information and create_tbl() returns zero (0) to indicate that an error has occurred.

Lines 282 to 287

This for loop controls the insertion of the canceltst rows. The MAX_ROWS constant determines the number of iterations for the loop, and hence the number of rows that the function inserts into the table. If you cannot interrupt the canceltst query (lines 126 to 132) because it executes too quickly, increase the value of MAX_ROWS and recompile the timeout.ec file.

Continued on page 12-66

Lines 288 to 292

This if statement generates the values for the char_fld1 and char_fld2 columns of the canceltst table. Lines 290 and 291 execute for odd-numbered rows. They store the strings "4100 Bohannon Dr" and "Menlo Park, CA" in the fld1 and fld2 variables, respectively.

Lines 293 to 297

Lines 295 and 296 execute for even-numbered rows. They store the strings Informix and Software in the fld1 and fld2 variables, respectively.

Lines 298 to 307

The INSERT statement inserts a row into the canceltst table. It takes the value for the int_fld column from the :i host variable (the row number), and the values for the char_fld1 and char_fld2 columns from the :fld1 and :fld2 host variables, respectively. The function notifies the user after it inserts every 1000 rows (lines 300 and 301). If the INSERT encounters an error, the exp_chk2() function (line 303) displays the diagnostics-area information and create_tbl() returns zero to indicate that an error has occurred.

Lines 300 to 317

These lines verify that the program has added the rows to the canceltst table and that it can access them. The program does a SELECT on the newly created canceltst table and returns the number of rows found. The program checks whether this number matches the number that the function has added, which line 309 displays. If the SELECT encounters an error, the exp_chk2() function (line 315) displays the diagnostics-area information, and create_tbl() returns 0 to indicate that an error has occurred.

Lines 320 to 329

The drop_tbl() function drops the canceltst table from the current database. If the DROP TABLE statement (line 324) encounters an error, the exp_chk2() function displays the diagnostics-area information and drop_tbl() returns 0 to indicate that an error has occurred.

Lines 330 to 336

Several of the ESQL/C demonstration programs also call the getans() function. Therefore, this function is broken out into a separate C source file and included in the appropriate demonstration program. Because this function does not contain ESQL/C, the program can use the C #include preprocessor statement to include the file. For a description of this function, see Guide to the inpfuncs.c File.

Lines 337 to 347

The prompt_ans() function displays the string in the question argument and waits for the user to enter y (yes) or n (no) as a response. It returns the single-character response.

Lines 348 to 355

The timeout program uses the exp_chk2(), sqlstate_err(), disp_error(), and disp_warning() functions to perform its exception handling. Because several demonstration programs use these functions, the exp_chk2() function and its supporting functions have been placed in a separate exp_chk.ec source file. The timeout program must include this file with the ESQL/C include directive because the exception-handling functions use ESQL/C statements. For a description of the exp_chk.ec file, see Guide to the exp_chk.ec File.

Tip: In a production environment, you would put functions such as getans(), exp_chk2(), sqlstate_err(), disp_error(), and disp_warning() into a library and include this library on the command line of the ESQL/C-program compilation.

Example Output

This section includes a sample output of the timeout demonstration program. This program performs two runs of the canceltst query, as follows:

The numbers that appear in the following output are for explanation only. They do not appear in the actual program output.

Continued on page 12-70

Lines 3 to 17

The create_tbl() function generates these lines. They indicate that the function has successfully created the canceltst table, inserted the MAX_ROWS number of rows (1,000), and confirmed that a SELECT statement can access these rows. For a description of the create_tbl() function, see the annotation beginning with Lines 262 to 281.

Lines 18 to 19

Line 18 displays the time-out interval to indicate that sqlbreakcallback() has successfully registered the callback function and established the time-out interval of 200 milliseconds (0.00333333 minutes). Line 19 asks the user to indicate the beginning of the query execution. This prompt prepares the user for the confirmation prompt (lines 28 and 43), which must be answered quickly to send an interrupt while the database server is still executing the query.

Line 20

This line indicates the beginning of the dspquery() function, the point at which the database server begins the canceltst query.

Lines 21 to 30

The program output uses a message-request box to indicate client-server communication:

Each box represents a single message request sent between the client and the server. The callback function displays the text for a message-request box. (For a description of which parts of the function display the text, see Lines 199 to 249.) To execute the OPEN statement, the client and server exchanged two message requests, which the two message-request boxes in the output indicate. For more information on message requests, see Interruptible SQL Statements.

The first message-request box (lines 21 to 23) indicates that the first message request completes before the time-out interval elapses. The second message-request box (lines 29 to 30) indicates that execution of this message request exceeds the time-out interval and calls the callback function with a status value of 2. The callback function prompts the user to confirm the interrupt request (line 28).

Line 29 indicates that the sqlbreak() function has requested an interrupt. The message request then completes (line 30).

Line 31

When the database server actually processes the interrupt request, it sets SQLCODE to -213. Line 31 indicates that the application program has responded to this status.

Line 32

This prompt indicates the end of the first run of the canceltst query. The user responds y to the prompt to run the query a second time.

Lines 36 to 41

The message-request box indicates that the first message request completes before the time-out interval elapses. The second message-request box (lines 39 to 44) indicates that execution of this message request again exceeds the time-out interval and calls the callback function (with when_called = 2). The callback function prompts the user to confirm the interrupt request (line 43). This time the user answers n.

Lines 45 to 52

Because the user has not interrupted the canceltst query, the program displays the row information that the query returns.

Lines 54 and 55

The drop_tbl() function generates these lines. They indicate that the function has successfully dropped the canceltst table from the database. For a description of the drop_tbl() function, see the annotation beginning with Lines 320 to 329.


INFORMIX-ESQL/C Programmer's Manual, Version 9.21
Copyright © 1999, Informix Software, Inc. All rights reserved