Example of retrieving a callback function

A temporary callback is useful when C UDRs are nested and some inner function wants to trap an event type in its own way instead of in the way that the outer function provides.

For example, suppose the func1() function specifies the func1_callback() function to handle event_type events and then calls the func2() function, as follows:
func1(...)
{
   MI_CALLBACK_HANDLE *cback_hndl;
   ...
   /* Set callback for event_type event type in func1() */
   cback_hndl = mi_register_callback(conn, event_type,
      func1_callback, ...)

   /* do some stuff */
   ...
   /* call func2(), which "inherits" func1() callback */
   func2()
   ...
}

func2()
{
   MI_CALLBACK_HANDLE *cback_hndl;
   MI_CALLBACK_FUNC *old_callback;

   /* Save func1() callback in 'old_callback' */
   if ( mi_retrieve_callback(conn, event_type, cback_hndl, 
         old_callback, NULL) == MI_ERROR )
      /* handle error */

   /* Set up func2() callback */
   mi_unregister_callback(conn, event_type, cback_hndl);
   mi_register_callback(conn, event_type, func2_callback, ...);

   /* do some other stuff */
   ...

   /* restore func1() callback */
   cback_hndl = mi_register_callback(conn, event_type,
      old_callback, ...)
   ...
}

By default, the database server uses the func1_callback() callback to handle any event_type events that occur during execution of func2(). For the func2() routine to trap an event_type event in its own way, the routine must save the func1_callback() callback and then register its own callback for the event_type event type.

In the preceding code, the func2() function performs the following tasks:
  1. Saves the func1_callback() from the func1() function.

    The func2() function passes in the func1_callback() callback handle (cback_hndl) to the mi_retrieve_callback() function, which puts the MI_CALLBACK_FUNC handle for func1_callback() into the old_callback argument.

  2. Registers its own callback, func2_callback() .

    The mi_register_callback() function registers the func2_callback() function for the event_type event type.

  3. Performs its own work .

    Any event_type event that occurs during this work causes the database server to invoke the func2_callback() function.

  4. Restores the callback of the func1() function.

    The func2() function uses mi_register_callback() again, this time to restore the func1_callback() as the callback for the event_type event type.

Server only:
For example, suppose the UDR func1() specifies the initial_cback() function to handle the MI_Exception event type, but the UDR requires the tmp_cback() callback for MI_Exception events during a portion of its execution. The following code fragment shows the use of mi_retrieve_callback() and mi_register_callback() to save the initial_cback() callback, to use the tmp_cback() callback temporarily, and then to restore initial_cback():
func1()
{
   MI_CONNECTION *conn;
   MI_CALLBACK_HANDLE *initial_hndl, *tmp_hndl;
   MI_CALLBACK_FUNC initial_cbptr;

   conn = mi_open(NULL, NULL, NULL);

   /* Register the initial callback (register #1). */
   initial_hndl = mi_register(conn, MI_Exception, 
      initial_cback, NULL, NULL);

   /* Do tasks that require initial_cback() as callback. */
   ...
   /* Retrieve the current callback-function pointer on
    * this connection into initial_cbptr. Pass in the
    * callback handle of initial_cback().
    */
   mi_retrieve_callback(conn, MI_Exception, initial_hndl,
      &initial_cbptr, NULL);
   /* Register the temporary callback (register #2).
    * Callback handle for initial callback is overwritten.
    */
   tmp_hndl = mi_register_callback(conn, MI_Exception,
      tmp_cback, NULL, NULL);

   /* Do tasks that require tmp_cback() as callback. */
   ...
   /* Restore initial callback (register #3) */
   initial_hndl = mi_register(conn, MI_Exception,
      &initial_cbptr, NULL, NULL);

   /* Continue with tasks that require initial_cback() as
    * callback.
    */
   ...
}