HPlogo ALLBASE/SQL C Application Programming Guide: HP 9000 Computer Systems > Chapter 4 Runtime Status Checking and the sqlca

Using the sqlca

» 

Technical documentation

Complete book in PDF
» Feedback

 » Table of Contents

 » Index

The SQLCA is used for communicating information between the application program and ALLBASE/SQL. SQL places information in the SQLCA each time it is called. Since there is no guarantee that information from one call to SQL will be present after the next call to SQL, any information needed from the SQLCA must be obtained after each call to ALLBASE/SQL.

Every ALLBASE/SQL program must have the SQL Communications Area (sqlca) declared in the global declaration part. You can use the INCLUDE command to declare the sqlca:



	EXEC SQL INCLUDE SQLCA;


When the preprocessor parses this command, it inserts the following type definition into the modified source file:



	sqlca_type sqlca;


Optionally, you can use this type definition in the global declaration part of your source file instead of using the INCLUDE command to declare the sqlca.

The C preprocessor generates the following record declaration for sqlca_type in the type declaration include file:



	typedef  struct  {

	  char   sqlaid[8];

	  int    sqlabc;

	  int    sqlcode;

	  int    sqlerrl;

	  char   sqlerrm[256];

	  char   sqlerrp[8];

	  int    sqlerrd[6];

	  char   sqlwarn[8];

	  char   sqlext[8];

	}  sqlca_type;


The following elements in this record are available for you to use in status checking and are accessed as follows. The other elements are reserved for use by ALLBASE/SQL only.



	sqlcode or sqlca.sqlcode

	sqlca.sqlerrd[2]

	sqlca.sqlwarn[0] or sqlca.sqlwarn0

	sqlca.sqlwarn[1] or sqlca.sqlwarn1

	sqlca.sqlwarn[2] or sqlca.sqlwarn2

	sqlca.sqlwarn[3] or sqlca.sqlwarn3    (used only for dynamic commands)

	sqlca.sqlwarn[6] or sqlca.sqlwarn6


NOTE: In conformance with the ANSI standard, either sqlcode or sqlca.sqlcode may be used to address this particular element. And each sqlwarn element can be addressed in two different ways.

The following table gives an overview of how ALLBASE/SQL sets these fields. Each field is then described with brief examples of how you can use it in one of two ways, including examples for using SQLEXPLAIN. Methods of handling specific status checking tasks are found in the succeeding section, "Approaches to Status Checking."

Table 4-1 sqlca Status Checking Fields

FIELD NAMESET TOCONDITION
sqlca.sqlcode or sqlcode

0

less than 0

100

no error occurred during command execution

error, command not executed

no rows qualify for DML operation (does not apply to dynamic commands)

sqlca.sqlerrd[2]

number of rows put into output host variables

number of rows processed

0

0

data retrieval operation

data change operation, [BULK]INSERT, Type 2 INSERT, UPDATE, or DELETE

error in single row data change operation

sqlcode equals 100

sqlca.sqlwarn[0] or sqlca.sqlwarn0Wwarning, command not properly executed
sqlca.sqlwarn[1] or sqlca.sqlwarn1Wat least one character string value was truncated when being stored in a host variable
sqlca.sqlwarn[2] or sqlca.sqlwarn2Wat least one null value was eliminated from the argument set of an aggregrate function
sqlca.sqlwarn[3] or sqlca.sqlwarn3Wfor dynamic commands only, when the number of host variables in a SELECT or FETCH is unequal to the number of columns in the table being operated on
sqlca.sqlwarn[6] or sqlca.sqlwarn6Wthe current transaction was rolled back

 

sqlcode

sqlcode can contain one of the following values:

  • 0, when an SQL command executes without generating an error condition and without generating a no rows qualify condition.

  • A negative number, when an error condition exists and an ALLBASE/SQL command cannot be executed.

  • 100, when no rows qualify for one of the following commands, but no error condition exists:

    	SELECT
    
    	INSERT
    
    	UPDATE (non-dynamic execution only)
    
    	DELETE (non-dynamic execution only)
    
    	BULK SELECT
    
    	FETCH
    
    	BULK FETCH
    
    	UPDATE WHERE CURRENT
    
    	DELETE WHERE CURRENT
    

Note that the absolute value of sqlcode is the same as the absolute value associated with its corresponding message in the ALLBASE/SQL message catalog. This absolute value is part of the returned message. If an error occurs, the message number is preceded by DBERR. For example, the error message associated with an sqlcode of -2613 is:



	Precision digits lost in decimal operation MULTIPLY.  (DBERR 2613)


Sqlcode is set by all SQL commands except the following directives:



	BEGIN DECLARE SECTION

	DECLARE

	END DECLARE SECTION

	INCLUDE

	WHENEVER


When sqlcode is -4008, -14024, or a greater negative value than -14024, ALLBASE/SQL automatically rolls back the current transaction. When this condition occurs, ALLBASE/SQL also sets sqlwarn[6] to W. Refer to the discussion later in this chapter on sqlwarn[6] for more on this topic.

More than one sqlcode is returned when more than one error occurs. For example, if you attempt to execute the following SQL command, two negative sqlcode values result:



	EXEC SQL ADD PUBLIC, GROUP1 TO GROUP GROUP1;


The sqlcodes associated with the two errors are:



	-2308, which indicates the reserved name PUBLIC is invalid.

	-2318, which indicates you cannot add a group to itself.


To obtain all sqlcodes associated with the execution of an SQL command, you execute the SQLEXPLAIN command until sqlcode is 0:

	    if (sqlca.sqlcode == 100) {

	      printf("No rows qualified for this operation.\n");

	      }

	    else

	      if (sqlca.sqlcode < 0) SQLStatusCheck();

                  .

                  .

                  .

	int SQLStatusCheck()

	{

	  do {

	  EXEC SQL SQLEXPLAIN :SQLMessage;

	  printf("%s\n",SQLMessage);

	  } while (sqlca.sqlcode != 0);

	  }


The function named SQLStatusCheck is executed when sqlcode is a negative number. Before executing SQLEXPLAIN for the first time, the program has access to the first sqlcode returned. Each time SQLEXPLAIN is executed subsequently, the next sqlcode becomes available to the program, and so on until sqlcode equals 0.

This example explicitly tests the value of sqlcode twice: first to determine whether it is equal to 100, then to determine whether it is less than 0. If the value 100 exists, no error will have occurred and the program will display the message, No rows qualify for this operation.

It is necessary for the program to display its own message in this case, because SQLEXPLAIN messages are available to your program only when sqlcode contains a negative number and when sqlwarn[0] contains a W.

The sqlcode is also used in implicit status checking:

  • ALLBASE/SQL tests for the condition sqlcode less than 0 when you use the SQLERROR option of the WHENEVER command.

  • ALLBASE/SQL tests for the condition sqlcode equal to 100 when you use the NOT FOUND option of the WHENEVER command.

In the following situation, when ALLBASE/SQL detects a negative sqlcode, the code routine at label a2000 is executed. When ALLBASE/SQL detects an sqlcode of 100, the code routine at label a4000 is executed instead:



	EXEC SQL WHENEVER SQLERROR GOTO a2000;

	EXEC SQL WHENEVER NOT FOUND GOTO a4000;


WHENEVER commands remain in effect for all SQL commands that appear physically after them in the source program until another WHENEVER command for the same condition appears.

The scope of WHENEVER commands is fully explained later in this chapter under "Implicit Error Handling Techniques."

sqlerrd[2]

sqlca.sqlerrd[2] can contain one of the following values:

  • 0, when sqlcode is 100 or when one of the following commands causes an error condition:

    
    
    	INSERT
    
    	UPDATE
    
    	DELETE
    
    	UPDATE WHERE CURRENT
    
    	DELETE WHERE CURRENT
    
    
    

    If an error occurs during execution of INSERT, UPDATE, or DELETE, one or more rows may have been processed prior to the error. In these cases, you may want to either COMMIT WORK or ROLLBACK WORK, depending on the transaction. For example, if all or no rows should be updated for logical data consistency, use ROLLBACK WORK. However, if logical data consistency is not an issue, COMMIT WORK may minimize re-processing time.

  • A positive number, when sqlcode is 0. In this case, the positive number provides information about the number of rows processed in the following data manipulation commands.

    The number of rows inserted, updated, or deleted in one of the following operations:

    
    
    
    
    	INSERT
    
    	UPDATE
    
    	DELETE
    
    	UPDATE WHERE CURRENT
    
    	DELETE WHERE CURRENT
    
    
    
    
    

    The number of rows put into output host variables when one of the following commands is executed:

    
    
    	SELECT
    
    	BULK SELECT
    
    	FETCH
    
    	BULK FETCH
    
    
    
  • A positive number, when sqlcode is less than 0. In this case, sqlerrd[2] indicates the number of rows that were successfully retrieved or inserted prior to the error condition:

    
    
    	BULK SELECT
    
    	BULK FETCH
    
    	BULK INSERT
    
    
    

    As in the case of INSERT, UPDATE, and DELETE, mentioned above, you can use either a COMMIT WORK or ROLLBACK WORK command, as appropriate.

sqlwarn[0]

A W in sqlwarn[0], in conjunction with a 0 in sqlcode, indicates that the SQL command just executed caused a warning condition.

Warning conditions flag unusual but not necessarily important conditions. For example, if a program attempts to submit an SQL command that grants an already existing authority, a message such as the following would be retrieved when SQLEXPLAIN is executed:



	User PEG already has DBA authorization.  (DBWARN 2006)


In the case of the following warning, the situation may or may not indicate a problem:



	A transaction in progress was aborted.  (DBWARN 2010)


This warning occurs when a program submits a RELEASE command without first terminating a transaction with a COMMIT WORK or ROLLBACK WORK. If the transaction did not perform any UPDATE, INSERT, or DELETE operations, this situation will not cause work to be lost. If the transaction did perform UPDATE, INSERT, or DELETE operations, the database changes are rolled back when the RELEASE command is processed.

You retrieve the appropriate warning message by using SQLEXPLAIN. Note that you can not explicitly test sqlwarn[0] the way you can test sqlcode, since sqlwarn[0] always contains W when a warning occurs.

An error and a warning condition may exist at the same time. In this event, sqlcode is set to a negative number, and sqlwarn[0] is set to W. Messages describing all the warnings and errors can be displayed as follows:



    if (sqlca.sqlcode != 0) {

      do {

      DisplayMessage();

      } while (sqlca.sqlcode != 0);

    }

    .

    .

    .

int DisplayMessage()

{

  EXEC SQL SQLEXPLAIN :SQLMessage;

  printf("%s\n",SQLMessage);

}

If multiple warnings but no errors result when ALLBASE/SQL processes a command, sqlwarn[0] is set to W and remains set until the last warning message has been retrieved by SQLEXPLAIN or another SQL command is executed. In the following example, DisplayWarning is executed when this condition exists:



	if ((sqlca.sqlcode == 0) & (sqlca.sqlwarn[0] == 'W')) {

	  do {

	  DisplayWarning();

	  } while (sqlca.sqlwarn[0] == 'W');

	  }

	  .

	  .

	  .

	int DisplayWarning()

	{

	  EXEC SQL SQLEXPLAIN :SQLMessage;

	  printf("%s\n",SQLMessage);

	}


When you use the SQLWARNING option of the WHENEVER command, ALLBASE/SQL checks for a W in sqlwarn[0]. You can use the WHENEVER command to do implicit status checking (equivalent to that done explicitly above) as follows:



	EXEC SQL WHENEVER SQLWARNING GOTO a3000;

	EXEC SQL WHENEVER SQLERROR GOTO a2000;


sqlwarn[1]

A W in sqlwarn[1] indicates truncation of at least one character string value when the string was stored in a host variable. Any associated indicator variable is set to the value of the string length before truncation.

For example:

	EXEC SQL SELECT  PartNumber,

	                 PartName

	           INTO :PartNumber

	                :PartName :PartNameInd

	           FROM  PurchDB.Parts

	          WHERE  PartNumber = :PartNumber;

If PartName was declared as a character array of 20 bytes, and the PartName column in the PurchDB.Parts table has a length of 30 bytes, then the following occurs:

  • sqlwarn[1] is set to W.

  • PartNameInd is set to 30 (the length of PartName in the table).

  • sqlcode is set to 0.

  • SQLEXPLAIN retrieves the message:

              Character string truncation during storage in host variable.
    
              (DBWARN 2040)
    

sqlwarn[2]

A W in sqlwarn[2] indicates that at least one null value was eliminated from the argument set of an aggregrate function.

For example:

	EXEC SQL SELECT  MAX(OrderQty)

	           INTO :MaxOrderQty

	           FROM  PurchDB.OrderItems;

If any OrderQty values are null, the following occurs:

  • sqlwarn[2] is set to W.

  • sqlcode is set to 0.

  • SQLEXPLAIN retrieves the message:

              NULL values eliminated from the argument of an aggregate
    
              function.   (DBWARN 2041)
    

sqlwarn[3]

A W in sqlwarn[3] indicates that the number of host variables specified in a dynamic SELECT or FETCH statement is unequal to the number of columns in the table being operated on.

For example:

	EXEC SQL PREPARE DynamicCommand from 'SELECT PartNumber, PartName

	                                        FROM PurchDB.Parts;';

	.



	EXEC SQL DESCRIBE DynamicCommand INTO SQLDA; /*sqlda.sqld is always set

	                                             at DESCRIBE by ALLBASE/SQL.*/

	EXEC SQL DECLARE DynamicCursor FOR DynamicCommand;

	EXEC SQL OPEN DynamicCursor;

	.

	/* Set up the sqlda for a fetch. */

	sqlda.sqlbuflen=sizeof(DataBuffer);

	sqlda.sqlnrow=((sqlbuflen)/(sqlrowlen));

	sqlda.sqlrowbuf=&databuffer;

	sqlda.sqld=1;   / *sqlda.sqld is incorrectly reset by the program. */

	.

	/* Do the fetch. */

	EXEC SQL FETCH DynamicCursor USING DESCRIPTOR SQLDA;

The FETCH will fail and the following occurs:

  • sqlwarn[3] is set to W.

  • sqlcode is set to -2762.

  • SQLEXPLAIN retrieves the message:

              Select list has ! items and host variable buffer has !.
    
              (DBERR 2762)
    

sqlwarn[6]

When an error occurs that causes ALLBASE/SQL to roll back the current transaction, sqlwarn[6] is set to W. ALLBASE/SQL automatically rolls back transactions when sqlcode is equal to -4008, or equal to or is less than -14024.

When such errors occur, ALLBASE/SQL does the following:

  • Sets sqlwarn[6] to W.

  • Sets sqlwarn[0] to W.

  • Sets sqlcode to a negative number.

If you want to terminate your program any time ALLBASE/SQL has to roll back the current transaction, you can just test sqlwarn[6].



	if (sqlca.sqlcode < 0) {

	  if (sqlca.sqlwarn[6] == 'W') {

	    SQLStatusCheck();

	    TerminateProgram();

	    }

	  else

	    SQLStatusCheck();

	  }


In this example, the program executes the function SQLStatusCheck when an error occurs. The program terminates whenever ALLBASE/SQL has rolled back a transaction, but continues if an error has occurred but was not serious enough to cause transaction roll back.

Feedback to webmaster