INFORMIX DataBlade Developers Kit Tutorial

List of Exercises

Exercise 4: Creating Row Data Types, continued


6

Generate the source code and the SQL registration scripts.

See " Generating Code" for detailed instructions.

BladeSmith generates the basic C code and SQL scripts necessary for your DataBlade module to run:

  • The source code is saved in the RowCircle\src\C directory.
  • The SQL scripts are saved in the RowCircle\scripts directory.

For more information about the Generate DataBlade command, see the DataBlade Developers Kit User's Guide.

The BladeSmith portion of this exercise is complete; you can exit BladeSmith.


7

Add source code to the templates generated by BladeSmith.

BladeSmith generates two source code files for the RowCircle DataBlade module:

  • udr.c. For the user-defined routines, rciDistance() and rciContains()
  • support.c. For tracing and BladeSmith utility functions (do not edit this file)

Add the following statement to the #include statements at the top of the udr.c file to include the C math library:

             #include <math.h> 
    
    

Because the rciContains() function calls the rciDistance() function, you must have a definition of the rciDistance() function in the udr.c file before the code for the rciContains() function.

Add the following rciDistance() function prototype directly after the #include statements in udr.c:

    UDREXPORT mi_double_precision *rciDistance
    ( 
     MI_ROW      * point1, 
     MI_ROW      * point2, 
     MI_FPARAM   * Gen_fparam 
     );
    
    

Implement the rciDistance() function.

To implement the rciDistance function

    1. Following the comment containing Your_Code ... BEGIN, find the comment that begins with TO DO: Remove this comment. Remove the comment and the mi_db_error_raise() statement and replace them with the following code:

             { 
              MI_DATUM x1, y1; 
              MI_DATUM x2, y2; 
              mi_integer retlen, retval; 
              /* Fetch values from rows */ 
              retval = mi_value(point1, 0, &x1, &retlen); 
              retval = mi_value(point1, 1, &y1, &retlen); 
              retval = mi_value(point2, 0, &x2, &retlen); 
              retval = mi_value(point2, 1, &y2, &retlen); 
    
    

    The elements of the rciPoint row data type, the x- and y-coordinates of a point, are extracted using the mi_value() statement and are stored in variables of type MI_DATUM. See the DataBlade API Programmer's Manual for information about handling data in row types.

    2. Look at the mi_alloc() statement that follows your just-entered code. BladeSmith generates this mi_alloc() statement to take care of memory allocation for the function's return value, Gen_RetVal:

          Gen_RetVal = 
                (mi_double_precision *)mi_alloc( sizeof( mi_double_precision ));
     
    

    3. Find the comment TO DO: Compute and store your value into Gen_RetVal. Replace the statement Gen_RetVal = 0; with the following code:

          *Gen_RetVal = 
                sqrt((*(mi_double_precision *)x1 - *(mi_double_precision *)x2) *
                (*(mi_double_precision *)x1 - *(mi_double_precision *)x2) +
                (*(mi_double_precision *)y1 - *(mi_double_precision *)y2) * 
                (*(mi_double_precision *)y1 - *(mi_double_precision *)y2));
         }
    
    

    The coordinates of each of the two points are cast from MI_DATUM to mi_double_precision values for the calculation.

Implement the rciContains() function by replacing the code between the comment containing Your_Code ... BEGIN and the comment containing Your_Code ... END with the following code fragment:

          {
            mi_double_precision * dist;
            mi_integer retlen;
            MI_DATUM center, radius;
                       
            /*
            ** Fetch values from rows
            */
            mi_value( circle, 0, &center, &retlen );
            mi_value( circle, 1, &radius, &retlen );
                       
            /*
            ** Computes the distance between
            ** the center of the circle and
            ** the point.
            */
            dist = rciDistance( point, center, Gen_fparam );
                       
            /* Is the distance within the radius? */
            if ((*dist - *(mi_double_precision *)radius) <= 0)
             {
                  Gen_RetVal = 1;
             }
            else
             {
                  Gen_RetVal = 0;
             }
           } 
    

BladeSmith makes the return value an mi_integer type, which is the closest available C data type to the SQL Boolean return type you defined. This mismatch between the C and SQL type systems is known as impedance. The C code in user-defined routines must map the routine's arguments and return values between the two type systems.

The elements of the rciCircle row data type, the radius and center of a circle, are extracted using the mi_value() statement and are stored in variables of type MI_DATUM. See the DataBlade API Programmer's Manual for information about handling row types in C.

To determine whether the point is contained within the circle, the rciContains() function first uses the rciDistance() function to calculate the distance between the center of the circle and the point. Then the rciContains() function subtracts the radius from the distance. If the result is negative, the point is contained by the circle; if the result is positive, the point is outside the circle.

In the subtraction, the radius is cast from an MI_DATUM type to an mi_double_precision type.

Check your source code against the final version of udr.c.

Save the changes to udr.c.


Copyright © 1998, Informix Software, Inc. All rights reserved.