| United States-English |
|
|
|
![]() |
ALLBASE/SQL COBOL Application Programming Guide: HP 9000 Computer Systems > Chapter 5 Runtime Status Checking and the SQLCAApproaches to Status Checking |
|
This section presents examples of how to use implicit and explicit status checking and to notify program users of the results of status checking. Implicit status checking is useful when control to handle warnings and errors can be passed to one predefined point in the program. Explicit status checking is useful when you want to test for specific SQLCA values before passing control to one of several locations in your program. Error and warning conditions detected by either type of status checking can be conveyed to the program user in various ways:
The WHENEVER command syntax has two components: a condition and an action. The command format is:
There are three possible WHENEVER conditions:
A WHENEVER command for each of these conditions can be in effect at the same time. There are three possible WHENEVER actions:
Any action may be specified for any condition. The WHENEVER command causes the COBOL preprocessor to generate status-checking and status-handling code for each SQL command that comes after it physically in the program until another WHENEVER command for the same condition is found. In the following program sequence, for example, the WHENEVER command in Procedure1 is in effect for SQLCommand1, but not for SQLCommand2, even though SQLCommand1 is executed first at run time:
The code that the preprocessor generates depends on the condition and action in a WHENEVER command. In the previous example, the preprocessor inserts a test for a negative SQLCODE and a sentence that invokes ERROR-HANDLER:
As the previous example illustrates, you can pass control to an exception-handling paragraph with a WHENEVER command, but you use a GO TO statement rather than a PERFORM statement. Therefore after the exception-handling paragraph is executed, control cannot automatically return to the paragraph which invoked it. You must use another GO TO or a PERFORM statement to explicitly pass control to a specific point in your program:
This exception-handling routine explicitly checks the first SQLCODE returned. The program terminates, or it continues from LineLabel after all warning and error messages are displayed. Note that a GO TO statement was required in this paragraph in order to allow the program to continue. Using a GO TO statement may be impractical when you want execution to continue from different places in the program, depending on the part of the program that provoked the error. This situation is discussed under "Explicit Status Checking" later in the chapter. The program illustrated in Figure 5-1 contains five WHENEVER commands:
The paragraph named S300-SERIOUS-ERROR is executed when an error occurs during the processing of session-related and transaction-related commands. The program terminates after displaying all available error messages. If a warning condition occurs during the execution of these commands, the warning condition is ignored, because the WHENEVER SQLWARNING CONTINUE command is in effect by default. The paragraph named S100-SQL-ERROR is executed when an error occurs during the processing of the SELECT command. S100-SQL-ERROR explicitly examines SQLCODE to determine whether a deadlock or shared memory problem occurred (SQLCODE = -14024 or -4008) or whether the error was serious enough to warrant terminating the program (SQLCODE < -14024):
In the case of any other errors, the program displays all available messages, then passes control to B110-EXIT. The paragraph named S500-SQL-WARNING is executed when only a warning condition results during execution of the SELECT command. This paragraph displays a message and the row of data retrieved. The NOT FOUND condition that may be associated with the SELECT command is handled by paragraph S600-NOT-FOUND. This paragraph displays the message, Part Number not found!, then passes control to B110-EXIT. SQLEXPLAIN does not provide a message for the NOT FOUND condition, so the program must provide one. The NOT FOUND condition generates code only for data manipulation commands. Had this program contained other data manipulation commands, NOT FOUND code would have been generated for each data manipulation command that occurred sequentially after the WHENEVER NOT FOUND command in the source code. Note also that none of the WHENEVER commands caused exception-handling code to be generated for SQLEXPLAIN. Figure 5-1 Implicitly Invoking Status-Checking Paragraphs
With explicit status checking, you invoke a paragraph after explicitly checking SQLCA values rather than using the WHENEVER command. The program in Figure 5-1 has already illustrated several uses of explicit status checking to:
The example in Figure 5-1 illustrates how implicit routines can sometimes reduce the amount of status checking code. As the number of SQL operations in a program increases, however, the likelihood of needing to return to different locations in the program after execution of such a routine increases. The example shown in Figure 5-2 contains four data manipulation operations: INSERT, UPDATE, DELETE, and SELECT. Each of these operations is executed from its own paragraph. As in the program in Figure 5-1, one paragraph is used for status checking: S100-SQL-ERROR. Unlike the program in Figure 5-1, however, this paragraph is invoked after explicit tests of SQLCODEs are made immediately following each data manipulation operation. Because the status-checking paragraph is invoked with a PERFORM command, it does not need to contain GO TO statements to return control to the point in the program where it was invoked. Figure 5-2 Explicitly Invoking Status-Checking Paragraphs
A deadlock exists when two transactions need data that the other transaction already has locked. When a deadlock occurs, ALLBASE/SQL rolls back the transaction with the larger priority number. If two deadlocked transactions have the same priority, ALLBASE/SQL rolls back the newer transaction. An SQLCODE of -14024 indicates that a deadlock has occurred:
An SQLCODE of -4008 indicates that ALLBASE/SQL does not have access to the amount of shared memory required to execute a command:
One way of handling deadlocks and shared memory problems is shown in the previous example, Figure 5-2. Another method would be to use a counter to reapply the transaction a specified number of times before notifying the user of the situation. SQLERRD(3) is useful in the following ways:
The example in Figure 5-2 could be modified to display the number of rows inserted, updated, or deleted by using SQLERRD(3). In the case of the update operation, for example, the actual number of rows updated could be displayed after the UPDATE command is executed:
If the UPDATE command is successfully executed, SQLCODE is OK (defined as zero in the WORKING-STORAGE SECTION) and SQLERRD(3) contains the number of rows updated. If the UPDATE command cannot be successfully executed, SQLCODE contains a negative number and SQLERRD(3) contains a 0. When using the BULK SELECT, BULK FETCH, or BULK INSERT commands, you can use the SQLERRD(3) value in several ways:
In the code identified as 1 in Figure 5-3, the value in SQLERRD(3) is displayed when only some of the qualifying rows could be retrieved before an error occurred. In the code identified as 2, the value in SQLERRD(3) is compared with the maximum array size to determine whether more rows might have qualified than the program could display. You could also use a cursor and execute the FETCH command until SQLCODE=100. In the code identified as 3, the value in SQLERRD(3) is used to control the number of times procedure DISPLAY-ROW is executed. Figure 5-3 Using SQLERRD(3) After a BULK SELECT Operation
Previous examples in this chapter have illustrated how an SQLCODE of 100 can be detected and handled for data manipulation commands that do not use a cursor. When a cursor is being used, this SQLCODE value is used to determine when all rows in an active set have been fetched:
In this example, the active set is defined when the OPEN command is executed. The cursor is then positioned before the first row of the active set. When the FETCH command is executed, the first row in the active set is placed into the program's host variables, then displayed. The FETCH command retrieves one row at a time into the host variables until the last row in the active set has been retrieved; the next attempt to FETCH after the last row from the active set has been fetched sets SQLCODE to NOTFOUND (defined as 100 in WORKING-STORAGE). If no rows qualify for the active set, SQLCODE is NOTFOUND the first time paragraph FETCH-ROW is executed. If more than one row qualifies for a non-BULK SELECT or FETCH operation, ALLBASE/SQL sets SQLCODE to -10002. In the following example, when SQLCODE is MULTIPLEROWS (defined as -10002 in WORKING-STORAGE), a status-checking paragraph is not invoked; instead a warning message is displayed:
Note that the PARTS table in the sample database has a unique index on PARTNUMBER, so a test for multiple rows is not required. This test is useful for the ORDERITEMS table which does not have a unique index. When the log file is full, log space must be reclaimed before ALLBASE/SQL can process any additional transactions. Your program can detect the situation, and it can be corrected by the DBA. SQLEXPLAIN retrieves the following message:
In the following example, SQLCODE is checked for a log full condition. If the condition is true, ALLBASE/SQL has rolled back the current transaction. The program issues a COMMIT WORK command, the S100-SQL-STATUS-CHECK routine is executed to display any messages, and the program is terminated.
It is possible that data or index space may be exhausted in a DBEFileSet. This could happen as rows are being added or an index is being created or when executing queries which require that data be sorted. Your program can detect the problem, and the DBA must add index or data space to the appropriate DBEFileSet. SQLEXPLAIN retrieves the following message:
In the following example, SQLCODE is checked for an out of space condition. If the condition is true, the transaction is rolled back to an appropriate savepoint. The program issues a COMMIT WORK command, the S100-SQL-STATUS-CHECK routine is executed to display any messages, and the program is terminated.
When the DBEUserID related to an ALLBASE/SQL command does not have the authority to execute the command, the following message is retreived by SQLEXPLAIN:
In the following example, SQLCODE is checked to determine if the user has proper connect authority. If the condition is true, the S100-SQL-STATUS-CHECK is executed to display any messages, and the program is terminated.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||