Handling multiple exceptions
The database server can generate multiple exceptions for a single SQL statement.
- Multiple warnings occur.
- Multiple details are associated with a single error occurrence.
For example, a DROP TABLE statement might set both the SQLCODE value and the ISAM error value. Similarly, nested UDRs might generate errors at many levels.
DataBlade® API function | Description |
---|---|
mi_error_desc_next() | Obtains the next error descriptor from the current
exception list The list of exceptions that the current statement generates is called the current exception list. |
mi_error_desc_finish() | Completes the processing of the current exception
list A callback can use this function to prevent its being called again for any more exceptions currently associated with the current statement. |
A callback is not called again for any messages that have already been processed. The database server presents exceptions from highest message level to lowest message level. Therefore, a UDR or SQL message occurs first, followed by any ISAM message.
- Call mi_error_sqlcode() to get the high-level SQLCODE value.
- Call mi_error_desc_next() to get the next error descriptor.
- Call mi_error_sqlcode() again to get the detailed smart-large-object error (and ISAM error code).
MI_CALLBACK_STATUS excpt_callback3(event_type, conn,
event_info, user_data)
MI_EVENT_TYPE event_type;
MI_CONNECTION *conn;
void *event_info;
void *user_data; /* user-defined error buffer gets
* passed here
*/
{
DB_ERROR_BUF *user_info;
mi_integer state_type;
mi_string *msg;
mi_integer i=0;
/* Pointer to multiple error messages */
MI_ERROR_DESC *err_desc=NULL;
user_info = ((DB_ERROR_BUF *)user_data);
user_info->error_type = event_type;
if ( event_type != MI_Exception )
{
user_info->sqlstate[0] = '\0';
sprintf(user_info->error_msg,
"excpt_callback3 called with wrong event type ",
"%d", event_type);
/* Send trace message for default trace class */
DPRINTF("__myErrors__", 1, ("<<<<>>>> mesg=%s",
user_info->error_msg));
return MI_CB_CONTINUE;
}
err_desc = (MI_ERROR_DESC *)event_info;
i++;
mi_error_sql_state(err_desc, user_info->sqlcode, 6);
mi_errmsg(err_desc, user_info->error_msg, MSG_SIZE-1);
DPRINTF("__myErrors__", 1,
("<<<<>>>> mesg %d: sqlcode=%s, mesg=%s", i,
user_info->sqlcode, user_info->error_msg));
/* Overwrites previous error. Another approach would be to
* allocate enough 'user_info' space to store all errors
*/
if ( (err_desc=
mi_error_desc_next((MI_ERROR_DESC *)event_info))
!= NULL )
{
i++;
mi_error_sql_state(err_desc, user_info->sqlcode, 6);
mi_errmsg(err_desc, user_info->error_msg,
MSG_SIZE-1);
DPRINTF("__myErrors__", 1,
("<<<<>>>> mesg %d: sqlcode=%s, mesg=%s", i,
user_info->sqlcode, user_info->error_msg));
}
return MI_CB_CONTINUE;
}
This callback also uses the DPRINTF macro to send trace messages to an output file.