Associate a user-defined error structure with a callback
To associate a user-defined error structure with the registered callback, specify the address of the structure as the fourth argument of mi_register_callback() function. The call to mi_register_callback() initializes the fourth parameter of the exception callback with a pointer to the user-defined structure.
For more information, see Initializing a callback.
Server only
The following func1() UDR
registers a callback named excpt_callback2(), which
puts error information in the DB_ERROR_BUF user-defined structure
(which A sample user-defined error structure defines):
void func1(flag)
mi_integer flag;
{
MI_CONNECTION *conn;
MI_CALLBACK_HANDLE *cback_hndl;
DB_ERROR_BUF error;
/* Initialize information in the error buffer */
error.sqlstate[0] = '\0';
strcpy(error.error_msg,
"func3: initialized error buffer.");
/* Obtain connection descriptor */
conn = mi_open(NULL, NULL, NULL);
if ( conn == NULL )
mi_db_error_raise(NULL, MI_EXCEPTION,
"func1: mi_open() call failed!");
/* Register the exception callback */
cback_hndl = mi_register_callback(conn, MI_Exception,
excpt_callback2, (void *)&error), NULL):
/* Execute SQL statement */
mi_exec(conn, "bad SQL statement", MI_QUERY_NORMAL);
/* Execution does not reach this point if the
* excpt_callback2() callback returns MI_CB_CONTINUE.
*/
The call to mi_register_callback() specifies
the address of the user-defined structure as its fourth argument.
This structure is, in turn, passed in as the third argument of the excpt_callback2() callback
(see Initializing a callback).
The following code implements the excpt_callback2() callback
function:
MI_CALLBACK_STATUS
excpt_callback2(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;
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_callback2 called with wrong event type ",
"%d", event_type);
}
else /* event_type is MI_Exception */
{
mi_error_sql_state((MI_ERROR_DESC *)event_info,
user_info->sqlstate, 6);
mi_errmsg((MI_ERROR_DESC *)event_info,
user_info->error_msg, MSG_SIZE-1);
}
return MI_CB_EXC_HANDLED;
}
Important: Make sure that you allocate the
user-defined error structure with a memory duration that is compatible
with the callback that uses it. Memory durations longer than PER_COMMAND
exist for use with end-of-statement, end-of-transaction, and end-of-session
callbacks. However, these longer memory durations must be used only
in special cases.
Client only
The following code fragment
from a client LIBMI application registers a callback named clntexcpt_callback2(),
which puts error information in the DB_ERROR_BUF user-defined structure
(which A sample user-defined error structure defines).
int main (argc, argv)
int argc;
char **argv;
{
MI_CONNECTION *conn = NULL;
char stmt[300];
MI_CALLBACK_HANDLE callback_hdnl;
DB_ERROR_BUF error_buff;
mi_integer ret;
/* Open a connection to the database server */
conn = mi_open(argv[1], NULL, NULL);
if ( conn == NULL )
/* do something appropriate */
/* Register the exception callback, with the user-defined
* error structure as the fourth argument to
* mi_register_callback()
*/
callback_hndl = mi_register_callback(conn, MI_Exception,
(MI_VOID *)clntexcpt_callback2;
(MI_VOID *)&error_buff, NULL);
if ( callback_hndl == NULL )
/* do something appropriate */
...
/* Execute the SQL statement that 'stmt' contains */
ret = send_statement(conn, stmt);
/* If an exception occurred during the execution of the
* SQL statement, the exception callback initialized the
* 'error_buff' structure. Obtain error information from
* 'error_buff'.
*/
if ( ret == MI_ERROR )
{
if ( error_buff.error_type == MI_Exception )
{
if ( error_buf.error_level == MI_EXCEPTION )
{
fprintf(stderr, "MI_Exception: level = %d",
error_buff.error_level);
fprintf(stderr, "SQLSTATE='%s'\n",
error_buff.sqlstate);
fprintf(stderr, "message = '%s'\n",
error_buff.error_msg);
/* discontinue processing */
}
else /* error_level is MI_WARNING */
{
sprintf(warn_msg, "WARNING: %s\n",
error_buf.error_msg);
display_msg(warn_msg);
}
}
/* do something appropriate */
...
}
The call to mi_register_callback() specifies
the address of the user-defined structure as its fourth argument.
This structure is, in turn, passed in as the fourth argument of the clntexcpt_callback2() callback.
The following code implements the clntexcpt_callback2() callback
function.
void clntexcpt_callback2(event_type, conn, event_info,
error_info)
MI_EVENT_TYPE event_type;
MI_CONNECTION *conn;
void *event_info;
void *error_info; /* user-defined error buffer here */
{
DB_ERROR_BUF *error_buf = (DB_ERROR_BUF *)error_info;
/* Fill user-defined structure with error information */
error_buf->error_type = event_type;
if ( event_type == MI_Exception )
{
error_buf->error_level = mi_error_level(event_info);
mi_error_sql_state(event_info, error_buf->sqlstate, 6);
mi_errmsg(event_info, error_buf->error_msg, MSG_SIZE-1);
}
else
fprintf(stderr,
"Warning! clntexcpt_callback() fired for event ",
"%d", event_type);
return;
}
The clntexcpt_callback() function is an example of an exception callback for a client LIBMI application. This callback returns void because the client LIBMI does not interpret the MI_CALLBACK_STATUS return value, as does the database server for UDRs.