Home | Previous Page | Next Page   Creating User-Defined Routines > Writing a User-Defined Routine > Coding a C UDR >

Defining Routine Parameters

When the routine manager invokes a C UDR, the routine manager passes to the UDR any argument values that the calling SQL statement provided. When you write a C UDR, you can define routine parameters that indicate the data types of the arguments that you expect the UDR to handle.

This section provides information about how to define routine parameters for the following UDR arguments:

Tip:
Routine arguments are optional; however, if your UDR does not require arguments, you must still declare an MI_FPARAM parameter in the C-function declaration. For more information, see MI_FPARAM Argument.

The routine manager uses the parameter data types in routine resolution. Therefore, you can have multiple UDRs with the same name, provided that their parameter lists uniquely identify the UDRs. For more information, see Routine Resolution.

Routines with No Arguments

Routine parameters are optional. If your UDR does not need parameters, follow your C-compiler conventions for the syntax to use when declaring the C function.

MI_DATUM Arguments

When an SQL statement invokes a UDR, the statement can specify column values or expressions to pass to the UDR. The routine manager passes these argument values to a UDR as MI_DATUM values. The data type of each argument determines the passing mechanism that the routine manager uses for the argument value, as follows:

The passing mechanism that the routine manager uses for a particular argument determines how you must declare the corresponding parameter of the UDR. For more information about how the routine manager passes argument values to a C UDR, see The MI_DATUM Data Type and Pushing Arguments Onto the Stack.

Pass-by-Reference Arguments

When an argument has a value that cannot fit into an MI_DATUM structure, the routine manager passes the argument by reference. For each of these pass-by-reference arguments, you declare a parameter that is a pointer to a value of the parameter data type, in the C-function declaration.

Figure 67 shows the bigger_double( ) user-defined function, which compares two mi_double_precision values. Because the routine manager passes mi_double_precision values by reference, bigger_double( ) declares the two parameters as pointers to values of the mi_double_precision data type.

Figure 67. Passing Arguments by Reference
mi_double_precision *bigger_double(left, right)
   mi_double_precision *left, *right;
{
   mi_double_precision *dpp;

   dpp = mi_alloc(sizeof(mi_double_precision));
   if ( *left > *right )
      {
      *dpp = *left;
      return(dpp);
      }
   else
      {
      *dpp = *right;
      return(dpp);
      }
}
Important:
Memory that the routine manager allocates to pass an argument by reference has a PER_ROUTINE memory duration. Therefore, it is guaranteed to be valid only for the duration of the UDR execution. The database server automatically frees this memory when the UDR completes.

Any C-language code that calls bigger_double( ) must pass the mi_double_precision values by reference, as in the following sample call:

mi_double_precision double1, double2, *result;

double1 = 13497.931669;
double2 = 235521832.00484;
result = bigger_double(&double1, &double2);

Tip:
For varying-length data, the routine manager does not pass a pointer to the actual data itself. Instead, it stores the varying-length data inside a varying-length structure. Therefore, your C UDR must declare parameters that expect varying-length data as a pointer to the appropriate varying-length structure. Varying-length data includes text arguments (see Handling Character Arguments) and varying-length opaque data types (see Handling Varying-Length Opaque-Type Arguments).

Values passed into a UDR are often also used in other places in the SQL statement. If your UDR modifies a pass-by-reference value, successive routines in the SQL statement might use the modified value. When your UDR is run within the context of an SQL statement, a routine that runs before it can see (and possibly modify) any pass-by-reference values.

Tip:
Avoid the modification of a pass-by-reference argument within a C UDR. For more information, see Modifying Argument Values.
Pass-by-Value Parameters

When an argument has a data type that can fit into an MI_DATUM structure, the routine manager passes the argument by value. Table 13 lists data types for arguments that you can pass by value. For these pass-by-value arguments, you declare a parameter as the actual parameter data type in the C-function declaration.

Figure 68 shows the bigger_int( ) UDR, which compares two mi_integer values. Because the routine manager passes mi_integer values by value, the UDR declares the two parameters with the mi_integer data type, not as pointers to mi_integer.

Figure 68. Passing Arguments by Value
mi_integer bigger_int(left, right)
   mi_integer left, right;
{
   if ( left > right )
      return(left);
   else
      return(right);
}

Any C-language code that calls bigger_int( ) must also pass the mi_integer values by value, as in the following sample call:

mi_integer int1, int2, result;
...
int1 = 6;
in2 = 8;
result = bigger_int(int1, int2);

MI_FPARAM Argument

The routine manager passes an MI_FPARAM structure into every UDR that it executes. This structure contains routine-state information about the UDR, such as information about arguments and return values. Because the routine manager automatically passes an MI_FPARAM structure to a UDR, you do not need to explicitly declare this structure in most C-function declarations.

You should include an MI_FPARAM declaration in the C-function declaration in the following cases:

For example, the bigger_double( ) user-defined function in Figure 67 does not include a declaration for the MI_FPARAM structure because it does not need to access routine-state information and it has other parameters. However, suppose you register a user-defined function named func_noargs( ) that does not require any arguments:

CREATE FUNCTION func_noargs( ) RETURNS INTEGER
   EXTERNAL NAME '/usr/lib/udrs/udrs.so' LANGUAGE C;

In the C UDR, you can declare the func_noargs( ) function with a single parameter, a pointer to the MI_FPARAM structure:

mi_integer func_noargs(MI_FPARAM *fparam)
{
...
}

The declaration of the MI_FPARAM structure allows the routine manager to pass this structure into the UDR.

Tip:
If your C UDR does not declare an MI_FPARAM structure but determines dynamically that it needs information in this structure, it can use the mi_fparam_get_current( ) function to obtain a pointer to its MI_FPARAM structure. This function, however, is an advanced feature. Make sure you need it before you use it in a C UDR.
Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]