Register an exception callback
When the database server or a UDR raises a database server exception, the database server invokes any callbacks that handle the MI_Exception event and that the UDR has registered (and enabled) on the current connection. Use the mi_register_callback() function to register such a callback.
#include <mi.h>
mi_integer
has_exception_handling(flag)
mi_integer flag;
{
static MI_CALLBACK_STATUS MI_PROC_CALLBACK
excpt_callback();
MI_CONNECTION *conn = NULL;
MI_CALLBACK_HANDLE *cback_hndl;
/* Obtain the connection descriptor */
conn = mi_open(NULL, NULL, NULL);
/* Register the 'excpt_callback' function as an
** exception callback */
cback_hndl = mi_register_callback(conn, MI_Exception,
excpt_callback, NULL, NULL);
/* Generate a syntax error that excpt_callback() will
** catch */
ret = mi_exec(conn, "bad SQL statement",
MI_QUERY_NORMAL);
if ( ret == MI_ERROR )
/* handle exception */
...
}
When the database server exception occurs in the SQL statement that mi_exec() executes, mi_exec() returns MI_ERROR and the if statement handles the exception. For a sample implementation of the excpt_callback() callback function, see Figure 1.
For the excpt_callback() function to be invoked for database exceptions that occur on the current connection, you must specify the connection descriptor of the current connection when you register excpt_callback(). In Figure 1, mi_register_callback() passes the conn connection descriptor, which the mi_open() call has obtained, when it registers excpt_callback().
The mi_open() function can be resource intensive. If your UDR is likely to be executed many times in the context of a single SQL statement, you might want to cache the connection descriptor from the initial mi_open() call in an MI_FPARAM structure. After you save this descriptor, you can reuse it in subsequent invocations of the UDR.
mi_integer
has_exception_handling2(flag, fparam)
mi_integer flag;
MI_FPARAM *fparam;
{
MI_CONNECTION *conn = NULL;
MI_CALLBACK_HANDLE *cback_hndl;
DB_ERROR_BUF error;
/* Obtain the connection descriptor from MI_FPARAM */
conn = (MI_CONNECTION *)mi_fp_funcstate(fparam);
if ( conn == NULL ) /* first time routine is called */
{
/* Obtain the connection descriptor */
conn = mi_open(NULL, NULL, NULL);
/* Register the 'excpt_callback2() function as an
** exception callback on this connection */
cback_hndl = mi_register_callback(conn,
MI_Exception,
excpt_callback2, (void *)&error, NULL);
/* Save connection descriptor in MI_FPARAM */
mi_fp_setfuncstate(fparam, (void *)conn);
}
...
}
In the preceding code fragment, the has_exception_handling2() routine registers the excpt_callback2() function as its exception callback. This callback uses a user-provided buffer to store event information. As its fourth argument, the mi_register_callback() call passes a user-defined buffer named error to the exception callback.