The database server can generate multiple exceptions for a single SQL statement. A single statement might generate multiple exceptions when any of the following conditions have occurred:
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.
The database server normally calls a registered exception callback once for each exception message. If a single error causes multiple exceptions, you must use the following DataBlade API functions in the callback to process multiple messages in a single invocation.
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.
The smart-large-object functions (mi_lo_*) raise an MI_Exception event if they encounter a database server exception. However, the smart-large-object error is the second message that the database server returns. Therefore, an exception callback needs to include the following steps to obtain an exception from an mi_lo_* function:
The following callback function, excpt_callback3( ), is a modified version of the excp_callback2( ) callback that handles multiple exceptions:
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. For more information on tracing, see Using Tracing.
Enterprise Edition Home | Express Edition Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]