Column values passed back to a C UDR (Server)
- For data types that are passed by value, the value buffer contains the actual column value.
- For data types that are passed by reference, the value buffer contains a pointer to this column value.
Therefore, within your C UDR, you cannot assume what the MI_DATUM value contains without checking its data type (or length).
MI_DATUM datum;
mi_integer length;
mi_char bool;
mi_short small;
mi_int large;
void *pointer;
switch ( mi_value( ..., &datum, &length ) )
{
....
} /* end switch */
/* Assume that 'datum' contains a BOOLEAN value
* (which uses only one byte of the MI_DATUM storage space).
* Pass the address of the actual data to another function.
* YOU CANNOT ALWAYS DO THIS!
* my_func( &datum, length );
* This address might point to the wrong byte! */
The preceding code fragment works if datum always contains a pointer to a column value or contains data the size of MI_DATUM. It might not work on some computer architectures, however, for data that is smaller than MI_DATUM (such as mi_boolean).
MI_ROW_DESC *row_desc;
MI_ROW *row;
MI_DATUM datum;
mi_integer length;
mi_boolean *bool;
mi_smallint *small_int;
mi_integer *full_int;
mi_date *date_val;
mi_string *col_type_name;
void *ptr_to_value;
...
switch ( mi_value(row, i, col_id, &datum, &length) )
{
...
case MI_NORMAL_VALUE:
col_type_name =
mi_type_typename(
mi_column_typedesc(row_desc, i));
/* To obtain the datum value and its address, first check
* if the value is passed by value. If not, assume that
* the value is passed by reference.
*/
switch( length )
{
/* Case 1: Assume that a length of one byte means
* that 'datum' contains a BOOLEAN value.
*/
case 1:
bool = (mi_boolean) datum;
ptr_to_value = &bool;
break;
/* Case 2: Assume that a length of two bytes means
* that 'datum' contains a SMALLINT value
*/
case 2:
small_int = (mi_smallint) datum;
ptr_to_value = &small_int;
break;
/* Case 4: Assume that a length of four bytes means
* that 'datum' contains an INTEGER or DATE value
*/
case 4:
if ( stcopy(col_type_name, "date") == 0 )
{
date_val = (mi_date) datum;
ptr_to_value = &date_val;
}
else /* data type is INTEGER */
{
full_int = (mi_integer) datum;
ptr_to_value = &full_int;
}
break;
/* Default Case: Assume that any for any other lengths,
* 'datum' contains a pointer to the value.
*/
default:
ptr_to_value = &datum;
break;
} /* end switch */
my_func( ptr_to_value );
The preceding code fragment handles only built-in data types that are passed by value. It was not written to handle all possible user-defined types (such as small fixed-length opaque types) because these do not have unique lengths.
mi_integer *small_int_ptr;
small_int = (mi_smallint) small_int_ptr;
This cast is necessary only for column values whose data types are passed by value because the MI_DATUM structure contains the actual column value, not a pointer to the value.
row_desc = mi_get_row_desc_without_row(conn);
...
switch ( mi_value(row, i, col_id, &datum, &length) )
{
...
case MI_NORMAL_VALUE:
if ( mi_type_byname(mi_column_typedesc(row_desc, i))
== MI_TRUE )
{
/* handle pass-by-value data types */;
The mi_type_byvalue() function helps to determine if a one-, two-, or four-byte value is actually passed by value. You can use this function to determine the passing mechanism of a fixed-length opaque data type.