Example: The get_data() function

The get_data() function retrieves data from a query that mi_exec() sends to the database server. This example makes the following assumptions:
  • The query data is in text representation because the original call to mi_exec() in the send_statement() function specifies the MI_QUERY_NORMAL control flag (see Example: The send_statement() function).
  • All the rows are of the same type and therefore share the same row descriptor (that is, no jagged rows).
The code for the get_data() function follows
/*
 * FUNCTION: get_data()
 * PURPOSE: Gets rows that a query returns.
 *
 * CALLED BY: get_results()
 * See Example: The get_results() function.
 */ 
#include "mi.h"  

mi_integer get_data( MI_CONNECTION *conn )
 {
    MI_ROW          *row = NULL;
    MI_ROW_DESC     *rowdesc;
    mi_integer      error;
    mi_integer      numcols;
    mi_integer      i;
    mi_string       *colname;
    mi_integer      collen;
    mi_string       *colval;
    mi_integer      is_nested_row;

    /* Get the row descriptor for the current statement */
    rowdesc = mi_get_row_desc_without_row(conn);

  /* Get the number of columns in the row */

     numcols = mi_column_count(rowdesc);

  /* Obtain the column names from the row desriptor */
    i = 0;
    while( i < numcols )
       {
       colname = mi_column_name(rowdesc, i);
       DPRINTF("trc_class", 11, ("  %s\t", colname));

        i++;
       }
    DPRINTF("trc_class", 11,("\n\n"));

  /* For each retrieved row: */
    while ( NULL != (row = mi_next_row(conn, &error)) )
       {
       /* For each column */
       for ( i = 0; i < numcols; i++ )
          {
          is_nested_row = MI_FALSE;

           /* Initialize column value and length */
          colval = NULL;
          collen = 0;

           /* Put the column value in colval */
          switch( mi_value(row, i, &colval, &collen) )
             {
             case MI_ERROR:
                mi_db_error_raise(conn, MI_EXCEPTION,
             "\nCannot get column value (mi_value)\n" );

              case MI_NULL_VALUE:
                colval = "NULL";
                break;

              case MI_NORMAL_VALUE:
                break;

              case MI_ROW_VALUE:
                is_nested_row = MI_TRUE;
                get_rowtype_data((MI_ROW *)colval);
                break;

              default:
                mi_db_error_raise(conn, MI_EXCEPTION,
                   "\nUnknown value (mi_value)\n" );
                return( -1 );
             }     /* end switch */

           if ( is_nested_row )
             {
             /* process row type */
             }
          else
             {
             /* Print the column value */
             DPRINTF("trc_class", 11, ("  %s\t", colval));
             }

           } /* end for */

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

     if ( MI_ERROR == error )
       {
       DPRINTF("trc_class", 11, ("\nReached last row\n"));
       }

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

     return(1); 
} 

The get_data() function calls mi_get_row_desc_without_row() to obtain the row descriptor and mi_column_count() to obtain the number of columns. It then calls mi_column_name() in a for loop to obtain and print the names of the columns in the row descriptor.

Server only: The get_data() function assumes it is called from within a C UDR. The function uses the DPRINTF statement, which is part of the DataBlade® API tracing feature and is available only to C UDRs. The first DPRINTF statement sends the name of each retrieved column to a trace file when the trace level is 11 or higher. Another DPRINTF statement sends the column value to the trace file. For more information about tracing, see Tracing.
Client only: For the get_data() function to execute in a client LIBMI application, it would need to replace the DPRINTF statement with a client-side output function such as printf() or fprintf(). The following code fragment uses the fprintf() function to display the names of retrieved columns:
while( i < numcols )
  {
    colname = mi_column_name(rowdesc, i);
    fprintf(stderr, "%s\t", colname);

    i++;
  }
fprintf(stderr, "\n\n");

All occurrences of DPRINTF would need to be replaced by appropriate client-side output functions.

In the outer loop, mi_next_row() obtains every row, and in the inner loop, mi_value() obtains every value in the row. The pointer returned in the value buffer is not valid after the next call to mi_value(). If the data were needed for later use, you would need to copy the data in the value buffer into a previously defined variable.

The get_data() function retrieves column data that is in text representation. The return values of the mi_value() function handle the text representations as follows:
  • For the MI_NORMAL_VALUE return value, get_data() breaks out of the switch statement.

    It does not need to perform any special handling based on column data type because values for all data types have the same data type: they are all null-terminated strings. Therefore, the colval variable that is passed into mi_value() is declared as a pointer to an mi_string. After mi_value() completes, colval points to the null-terminated string for the column value.

  • For the MI_NULL_VALUE return value, get_data() assigns the string NULL as the column value.

    The mi_value() function does not assign a null-terminated string to a column value when the column contains the SQL NULL value. Therefore, get_data() explicitly sets the column value to hold the null-terminated string: NULL.

  • For the MI_ROW_VALUE return value, get_data() calls the get_row_data() function to handle the row structure.

    The get_row_data() function obtains values from the row structure in their text representation. For more information, see Obtain row values.

  • The get_data() function does not handle the MI_COLLECTION_VALUE return status.

    The mi_value() function returns the MI_NORMAL_VALUE value status for a collection column when the query is in text representation. For sample code that handles a collection column when query data is in binary mode, see A collection in binary representation.