Text input and output functions

The text input function converts from the textual representation of an opaque data type to the internal format. The C name of the text input function for each opaque data type is OpaqueInput(). The text output function converts from the internal format of an opaque data type and the textual representation. The C name of the text output function for each opaque data type is OpaqueOutput().

BladeSmith generates complete C code for these functions.

The generated code

The generated code for the text input and output functions uses a default text representation: a string containing all members of the structure, delimited with spaces.

Strings are enclosed in quotation marks ('). Large objects are represented as external file names enclosed in quotation marks. The input function calls the sscanf() C library function. Use character representations for these types that sscanf() recognizes.

For example, the Circle DataBlade® module defines a Pnt data type with two mi_double_precision members, x and y. The Circ.h header file contains the following structure definition:
typedef struct
{
   mi_double_precision            x;
   mi_double_precision            y;
}
Pnt;
The default text representation for the Pnt data type is as follows:
'x y'
where x and y are character strings that sscanf() can convert to double-precision values. For example, the following statement inserts a Pnt value into a table by using the default text representation:
insert into mytable (col1) values ('12.3 66.9');

Text input function

The text input function has two arguments: an mi_lvarchar pointer, which points to the text that is to be converted, and an unused MI_FPARAM pointer.

The text input function returns a pointer to a filled-in C structure for the Pnt data type. The contents of this structure are written to the database table. The function allocates memory for the opaque type it returns, as follows:

   /* Allocate memory room to build the UDT in. */
   Gen_RetVal = (Pnt *)mi_alloc( sizeof(Pnt));
   if(Gen_RetVal == 0)
   {
      /*
      ** Memory allocation has failed so issue
      ** the following message and quit.
      **
      **    "Memory allocation has failed in PntInput."
      */
      mi_db_error_raise(Gen_Con, MI_SQL, ERRORMESG2,
         "FUNCTION%s", "PntInput", (char *)NULL);

The database server frees the allocated memory.

Next, the function scans the text string, obtaining a value for one structure member at a time, as follows:
   /* Get the data value for Gen_OutData->x. */
   Gen_InData = Gen_sscanf(Gen_Con, "PntInput", Gen_InData,
            mi_get_varlen(Gen_param1), 0,
            "%lf %n",
            (char *)&Gen_OutData->x);

   /* Get the data value for Gen_OutData->y. */
   Gen_InData = Gen_sscanf(Gen_Con, "PntInput", Gen_InData,
            mi_get_varlen(Gen_param1), 0,
            "%lf %n",
            (char *)&Gen_OutData->y);

This code calls the Gen_sscanf() utility function, which BladeSmith adds to each generated C source file.

Finally, the text input function returns a pointer to the completed C structure, as follows:
   /* Return the UDT value. */
   return Gen_RetVal;

Text output function

The text output function takes a pointer to the opaque type structure and an MI_FPARAM pointer and returns a text representation of the data type in an mi_lvarchar value.

BladeSmith operates under the assumption that the text representation is a string containing character representations of all of the structure members delimited with spaces. The function encloses strings and filenames for large objects in double quotation marks.

The generated text output function computes the maximum length of the string it returns and calls mi_new_var() to allocate an mi_lvarchar argument, Gen_RetVal. The database server frees the allocated memory later.

The function calls the C standard library function sprintf() once for each structure member to write the value and a space in the data area pointed to by the Gen_OutData argument. The following code shows the sprintf() calls from the generated PntOutput() function in the Circle DataBlade module:
   /* Format the value for Gen_InData->x. */
   sprintf(Gen_OutData, "%lf ", Gen_InData->x);
   Gen_OutData += strlen(Gen_OutData);

   /* Format the value for Gen_InData->y. */
   sprintf(Gen_OutData, "%lf", Gen_InData->y);
   Gen_OutData += strlen(Gen_OutData);

Between calls to sprintf(), the function resets Gen_OutData to point to the end of the string.

Customize the code

To use an input text format different from the default format, or if the C structure contains data types that BladeSmith cannot scan with Gen_sscanf(), you must modify the generated text input function code.

If you want an input text format that is different from the default, replace the generated code with your own. For example, you can choose to delimit values with commas instead of spaces. Your code might be able to call the Gen_sscanf() function, or you might need to write your own scanning function.

In the Circle DataBlade module, the text representation of the Pnt data type is changed from the default format, 'x y', to a new format: '(x, y).'

To support the new format, Gen_sscanf() calls in the PntInput() function are modified to include the parentheses and comma in the format string, as shown in the following code:
   /* Get the data value for Gen_OutData->x. */
   Gen_InData = Gen_sscanf(Gen_Con, "PntInput", Gen_InData,
            mi_get_varlen(Gen_param1), 0,
            "(%lf %n,",
            (char *)&Gen_OutData->x);

   /* Get the data value for Gen_OutData->y. */
   Gen_InData = Gen_sscanf(Gen_Con, "PntInput", Gen_InData,
            mi_get_varlen(Gen_param1), 0,
            "%lf %n)",
            (char *)&Gen_OutData->y);

If you change the text input function to support a text format different from the default, also change the text output function. The string returned by the text input function is a valid string for the text output function.

For example, to support the new text representation for the Pnt data type, the parentheses and comma are added to the sprintf() calls in the PntOutput() function, as follows:
   /* Format the value for Gen_InData->x. */
   sprintf(Gen_OutData, "(%lf,", Gen_InData->x);
   Gen_OutData += strlen(Gen_OutData);

   /* Format the value for Gen_InData->y. */
   sprintf(Gen_OutData, "%lf)", Gen_InData->y);
   Gen_OutData += strlen(Gen_OutData);

Smart large object considerations

Large objects are represented as external file names enclosed in quotation marks.

Examples

The following example DataBlade modules contain text input and output functions:
Table 1. Example DataBlade modules that contain input and output functions
Example DataBlade module Description
Strings DataBlade module The text input and output functions for the CompressStr opaque data type call user-defined routines to compress and uncompress a string, use the MI_FPARAM argument, and pass a smart large object handle.
Circle DataBlade module The text input and output functions for the Pnt opaque data type show a modified text representation.
Shapes DataBlade module The text input and output functions for the MyShape opaque data type contain code for each of the three specific cases of MyShape: MyBox, MyCircle, and MyPoint. The text input and output functions for the MyBox, MyCircle, and MyPoint data types call the text input and output functions for MyShape.
FuzzyMatch DataBlade module The text input function for the ColorType opaque data type converts the textual name of a color to a three-integer value by looking up the value in a map file.
UDTExporter DataBlade module The text input and output functions for the ComplexNumber opaque data type process an integer array.
MMXImage DataBlade module The text input and output functions process the variable-length Image opaque data type by using MMX technology.