Building a save set

To build a save set, a DataBlade® API module can create a save set and fetch rows into it from the mi_next_row() loop.

About this task

The rows inserted into the save set are copies of the rows in the database, so modifications to the database after a row is inserted into a save set are not reflected in the save set. In effect, the save set stores stale rows.

To build a save set:

Procedure

  1. Create the save set with mi_save_set_create().
  2. Execute the query to select rows from the database (for example, with mi_exec()).
  3. When mi_get_result() returns MI_ROWS, initiate an mi_next_row() loop to get the rows.
  4. Inside the mi_next_row() loop, for each row that you want to save in the save set, invoke mi_save_set_insert().

Results

The user function build_saveset() creates a save set and inserts rows into it. It is called when mi_get_result() returns MI_ROWS and the application wants to store the rows temporarily in a save set. Another user function, get_saveset_data(), is called to access and manipulate the data in the save set.
/*
 * Example of how to build a save set.
 */
#include <mi.h>

mi_integer build_saveset( MI_CONNECTION *conn)
   {
   MI_SAVE_SET  *save_set;
   MI_ROW       *row;
   MI_ROW       *row_in_saveset;

   mi_integer   error;

   save_set = mi_save_set_create(conn);

   if ( NULL == save_set )
      {
      DPRINTF("trc_class", 11,
         ("Could not create save set\n"));
      return (-1);
      }

/* Insert each row into the save set */
   while( NULL != (row = mi_next_row(conn, &error)) )
      {

      row_in_saveset = mi_save_set_insert(save_set, row);

      if( NULL == row_in_saveset )
         {
         mi_db_error_raise(conn, MI_MESSAGE,
            "Could not insert into save set\n");
         return (-1);
         }
      } /* end while */

/* Check reason for mi_next_row() completion */
   if ( error == MI_ERROR )
   {
    mi_db_error_raise(conn, MI_MESSAGE, 
      "Could not get next row\n" );
    return(-1);
   }

/* Print out message to trace file */
   DPRINTF("trc_class", 11, 
      ("%d rows inserted in save set\n",
      mi_save_set_count(save_set)));

   get_saveset_data(save_set);

   error =  mi_save_set_destroy(save_set);
   if( MI_ERROR == error )
      {
      mi_db_error_raise(conn, MI_MESSAGE, 
         "Could not destroy save set\n" );
      return (-1);
      }

   return(0);
}

After the build_saveset() function successfully completes, the get_saveset_data() function can traverse the save set as a FIFO queue. The mi_save_set_get_first() function retrieves the first row of the save set, which is the most recently added row. The DataBlade API module can scan forward through the save set with mi_save_set_get_next() and then backward with mi_save_set_get_previous(). All of these routines return a pointer to the row structure (MI_ROW) for the current row in the save set.

The following function, get_saveset_data(), traverses the save set:
/*
 * Get Save-Set Data Example
 */
#include "mi.h"

mi_integer get_saveset_data( MI_SAVE_SET *save_set)
   {
   MI_ROW          *row;
   MI_ROW_DESC     *rowdesc;
   mi_integer      error;
   mi_integer      numcols;
   mi_integer      i;
   char            *colname;
   mi_integer      collen;
   char            *colval;

/* Get the first row from the save set */
   row = mi_save_set_get_first(save_set, &error);
   if (error == MI_ERROR)
      {
      DPRINTF("trc_class", 11, 
         ("Could not get first row from save set\n"));
      return(-1);
      }

/* Get the description of the row */
   rowdesc = mi_get_row_desc(row);

/* Get the number of columns in the row */
   numcols = mi_column_count(rowdesc);

/* Print the column names */
   for ( i = 0; i < numcols; i++ )
      {
      colname = mi_column_name(rowdesc, i);
      DPRINTF("trc_class", 11, ("%s\t", colname));
      } /* end for */

   DPRINTF("trc_class", 11, ("\n\n"));

/* For each column */
   for ( i = 0; i < numcols; i++ )
      {
      switch( mi_value(row, i, &colval, &collen) )
         {
         case MI_ERROR:
            DPRINTF("trc_class", 11, 
               ("\nCannot get value\n"));
            return(-1);

         case MI_NULL_VALUE:
            colval = "NULL";
            break;

         case MI_NORMAL_VALUE:
            break;

         default:
            DPRINTF("trc_class", 11, 
               ("\nUnknown value\n"));
            return(-1);

         } /* end switch */

      DPRINTF("trc_class", 11, ("%s\t", colval));
      } /* end for */
 
/* For each row */
   while ( (row = mi_save_set_get_next(save_set, &error))
         != NULL )
      {
      if ( error == MI_ERROR )
         {
         DPRINTF("trc_class", 11, 
            ("\nCould not get next row"));
         return (-1);
         }

/* For each column */
      for ( i = 0; i < numcols; i++ )
         {
         switch( mi_value(row, i, &colval, &collen) )
            {
            case MI_ERROR:
               DPRINTF("trc_class", 11, 
                  ("\nCannot get value\n"));
               return(-1);

            case MI_NULL_VALUE:
               colval = "NULL";
               break;

            case MI_NORMAL_VALUE:
               break;

            default:
               DPRINTF("trc_class", 11, 
                  ("\nUnknown value\n"));
               break;

            } /* end switch */

         DPRINTF("trc_class", 11, ("%s\t", colval));

         } /* end for */

      DPRINTF("trc_class", 11, ("\n"));

      } /* end while */
 
   DPRINTF("trc_class", 11, ("\n"));
   return(1);
}

When a row is obtained from the save set, its values are extracted using an mi_value() loop, as demonstrated in Example: The get_data() function.