A function descriptor, MI_FUNC_DESC, contains static information about a UDR that is to be invoked with the Fastpath interface. It is basically a structured version of the row in the sysprocedures system catalog table that describes the UDR. The function descriptor also identifies the routine sequence for the associated UDR. (For more information on the routine sequence, see Creating the Routine Sequence.)
The following table summarizes the memory operations for a function descriptor.
A calling DataBlade API module uses a function descriptor as a handle to identify the UDR it needs to invoke with the Fastpath interface. To obtain a function descriptor, call one of the Fastpath look-up functions in Table 65.
To look up a UDR, use one of the following Fastpath look-up functions.
The mi_func_desc_by_typeid( ) function is available only within a C UDR. It is not valid within a client LIBMI application.
To obtain a function descriptor for a UDR, a Fastpath look-up function performs the following steps:
If the name of the UDR in the routine signature that you specify is not unique in the database, the mi_routine_get( ) and mi_routine_get_by_typeid( ) functions use the routine signature to perform routine resolution. For more information, see Routine Resolution.
A routine identifier uniquely identifies a UDR, so the mi_func_desc_by_typeid( ) function does not need to perform routine resolution. The routine identifier corresponds to the entry for the UDR in sysprocedures.procid. A negative routine identifier indicates a built-in function that does not have an entry in sysprocedures. The database server looks up information for a built-in function in an internal cache.
You can obtain information about the UDR from this function descriptor. For more information, see Obtaining Information from a Function Descriptor. You can also allocate your own MI_FPARAM structure to use instead of this automatically allocated one. For more information, see Using a User-Allocated MI_FPARAM Structure.
You can get a pointer to this structure with the mi_fparam_get( ) function. For more information, see Obtaining the MI_FPARAM Structure.
Subsequent calls to mi_routine_exec( ) can use this function descriptor to identify the UDR to execute. For more information, see Executing the Routine.
Suppose the following CREATE FUNCTION statements register three user-defined functions named numeric_func( ) in your database:
CREATE FUNCTION numeric_func(INTEGER, INTEGER) RETURNS INTEGER; CREATE FUNCTION numeric_func(FLOAT, FLOAT) RETURNS FLOAT; CREATE FUNCTION numeric_func(MONEY, MONEY) RETURNS MONEY;
The numeric_func( ) user-defined function is an overloaded routine. The code fragment in Figure 51 uses the mi_routine_get( ) function to obtain the function descriptor for the version of numeric_func( ) that handles INTEGER arguments.
MI_CONNECTION *conn; MI_FUNC_DESC *fdesc = NULL; MI_FPARAM *fparam; ... fdesc = mi_routine_get(conn, 0, "function numeric_func(integer, integer)"); if ( fdesc =! NULL ) { fparam = mi_fparam_get(conn, fdesc); if ( mi_fp_nrets(fparam) > 1 ) /* multiple return values: have SPL routine */ ... else /* no matching user-defined routine*/ ... }
The mi_routine_get( ) function returns a NULL-valued pointer to indicate either no matching routine exists or the routine has multiple return values. Figure 51 also shows how to determine which of these conditions a NULL return value indicates. It uses the mi_fparam_get( ) function to obtain the MI_FPARAM structure that is associated with the located numeric_func( ) function. (The mi_routine_get( ) function has allocated and initialized this MI_FPARAM structure as part of the look-up process.) The code fragment then uses the mi_fp_nrets( ) accessor function to obtain the number of UDR return values from this MI_FPARAM structure. Because C UDRs can only return one value, any UDR that returns more than one value must be an SPL routine.
Use mi_routine_get( ) when you can create the full signature of the UDR as a literal string. Otherwise, you can use the mi_routine_get_by_typeids( ) function to build the routine signature. For example, if you have a user-supplied query, you could use mi_column_typeid( ) to get the type identifier for the column that the query returns. The mi_routine_get_by_typedesc( ) function is also useful when you need to invoke overloaded UDRs with different parameter data types (and you have parameter type identifiers).
In Figure 51, you could replace the call to mi_routine_get( ) with the following call to the mi_routine_get_by_typeid( ) function:
MI_TYPEID *arg_types[2]; ... arg_type[0] = mi_typestring_to_id(conn, "integer"); arg_type[1] = arg_type[0]; fdesc = mi_routine_get_by_typeid(conn, MI_FUNC, "numeric_func", NULL, 2, arg_types);
In this call to mi_routine_get_by_typeid( ), the arg_types array contains pointers to the type identifiers for the two INTEGER parameters.
If you already have a routine identifier for the UDR that you want to execute with Fastpath, use the mi_func_desc_by_typeid( ) function to obtain the function descriptor of the UDR. In Figure 51, you could replace the call to mi_routine_get( ) with the following call to mi_func_desc_by_typeid( ):
mi_funcid rout_id; ... fdesc = mi_func_desc_by_typeid(conn, rout_id);
In this call, the mi_funcid data type holds the routine identifier of the UDR to look up.
When you call mi_routine_get( ) or mi_routine_get_by_typeid( ) from a client LIBMI application, the function allocates a local copy (on the client computer) of the function descriptor and MI_FPARAM structure. You can use the function descriptor and MI_FPARAM accessor functions within a client LIBMI application to access these local copies.
The mi_func_desc_by_typeid( ) function is not valid within a client LIBMI application.
A cast function is a user-defined function that converts one data type (the source data type) to a different data type (the target data type).
The way that a cast is called depends on the type of the cast, as the following table shows.
To look up a cast function by its source and target data types, use one of the following Fastpath look-up functions.
To obtain a function descriptor for a cast function, the mi_cast_get( ) or mi_td_cast_get( ) function performs the following steps:
Once the function locates a syscasts entry for the cast function, it obtains routine information for the cast function from the sysprocedures system catalog table. These functions also determine the type of cast that the cast function performs: an explicit cast, an implicit cast, or a built-in cast.
You can obtain information about the UDR from this function descriptor. For more information, see Obtaining Information from a Function Descriptor.
You can get a pointer to this structure with the mi_fparam_get( ) function. For more information, see Obtaining the MI_FPARAM Structure. You can also allocate your own MI_FPARAM structure to use instead of this automatically allocated one. For more information, see Using a User-Allocated MI_FPARAM Structure.
Subsequent calls to mi_routine_exec( ) can use this function descriptor to identify the cast function to execute. For more information, see Executing the Routine.
Suppose the following CREATE CAST statements register explicit casts between the DECIMAL and mytype data types in your database:
CREATE CAST (mytype AS DECIMAL(5,3) WITH mt_to_dec); CREATE CAST (DECIMAL(5,3) AS mytype WITH dec_to_mt);
Figure 52 uses the mi_cast_get( ) function to obtain the function descriptor for a cast function that casts from a DECIMAL data type to the mytype data type.
MI_CONNECTION *conn; MI_FUNC_DESC *fdesc2 = NULL; MI_TYPEID *src_type, *trgt_type; mi_char cast_status = 0; mi_boolean need_cast = MI_TRUE; mi_integer error; MI_DATUM *ret_val; mi_decimal dec_val; ... /* Get type identifiers for source and target types */ src_type = mi_typestring_to_id(conn, "DECIMAL(5,3)"); trgt_type = mi_typestring_to_id(conn, "mytype"); /* Look up cast function based on type identifiers */ fdesc2 = mi_cast_get(conn, src_type, trgt_type, &cast_status); switch ( cast_status ) { case MI_ERROR_CAST: /* error in function look-up */ mi_db_error_raise(NULL, MI_EXCEPTION, "mi_cast_get( ) failed"); break; case MI_NO_CAST: /* no cast function exists */ mi_db_error_raise(NULL, MI_EXCEPTION, "No cast function found"); break; case MI_NOP_CAST: /* do not need a cast */ need_cast = MI_FALSE; break; } if ( need_cast ) /* Execute the cast function with Fastpath */ ...
The mi_cast_get( ) function allocates and initializes a function descriptor, fdesc2, for the dec_to_mt( ) cast function. The src_type and trgt_type variables are pointers to the type identifiers for the DECIMAL(5,3) and mytype data types, respectively.
The mi_cast_get( ) function returns a NULL-valued pointer to indicate several different conditions. In Figure 52, the cast_status variable identifies which of these conditions has occurred, as follows.
cast_status Value | Condition |
---|---|
MI_ERROR_CAST | The mi_cast_get( ) function has not executed successfully. |
MI_NO_CAST | No cast function exists between the specified source and target types. |
MI_NOP_CAST | No cast function is needed between the specified source and target types. |
The switch statement handles the possible status cast_status values from the mi_cast_get( ) call.
If you have type descriptors instead of type identifiers for the source and target types, use the mi_td_cast_get( ) function instead of mi_cast_get( ). For example, the casting process might need information about scale and precision for built-in data types that have this information. A type descriptor stores scale and precision; a type identifier does not.
You could replace the call to mi_cast_get( ) in Figure 52 with the following call to the mi_td_cast_get( ) function:
MI_TYPEID *src_type, *trgt_type; MI_TYPE_DESC *src_tdesc, *trgt_tdesc; ... /* Get type descriptors for source and target types */ src_tdesc = mi_type_typedesc(conn, src_type); trgt_tdesc = mi_type_typedesc(conn, trgt_type); /* Look up cast function based on type descriptors */ fdesc2 = mi_td_cast_get(conn, src_tdesc, trgt_tdesc, &cast_status);
The src_tdesc and trgt_tdesc variables are pointers to type descriptors for the DECIMAL(5,3) and mytype data types, respectively. The mi_type_typedesc( ) function creates type descriptors from the type identifiers that src_type and trgt_type reference.
When you call mi_cast_get( ) or mi_td_cast_get( ) from a client LIBMI application, the function allocates a local copy (on the client computer) of the function descriptor and MI_FPARAM structure. You can use the function-descriptor and MI_FPARAM accessor functions within a client LIBMI application to access these local copies.