The DataBlade API provides the mi_call( ) function to dynamically manage stack space. This function performs the following tasks:
Use the mi_call( ) function to increase stack space for recursive UDRs.
Keep in mind that mi_call( ) does not know the size of the routine arguments. When mi_call( ) creates a new stack and copies an argument onto this new stack, the function uses the size of the MI_DATUM data type for the argument. If the data type of the routine argument is larger than MI_DATUM, mi_call( ) does not copy all the argument bytes.
For example, consider a UDR that includes an mi_double argument.
On UNIX or Linux, an mi_double_precision argument takes the space of two long int values. Therefore, the mi_call( ) function pushes only half of the argument onto the new stack. Any arguments after the mi_double_precision might get garbled, and the last one might be truncated.
When you design UDRs that require the use of mi_call( ), make sure you use the correct passing mechanism for the argument data type. Pass all data types larger than MI_DATUM by reference. Examples of large data types are floating-point types (such as mi_real and mi_double_precision) and data type structures.
The following example illustrates stack-space allocation with mi_call( ):
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "mi.h" mi_integer factorial(mi_integer value) { mi_integer callstatus=0, retval=0; if ( value < 0 ) return -1; else if ( value == 1 || value == 0 ) return 1; else if ( value > 30 ) mi_db_error_raise(NULL, MI_EXCEPTION, "factorial: input value too big for result."); callstatus = mi_call(&retval, factorial, 1, value-1); switch( callstatus ) { case MI_TOOMANY: mi_db_error_raise(NULL, MI_EXCEPTION, "factorial: too many parameters."); case MI_CONTINUE: return (value * factorial(value-1)); case MI_NOMEM: mi_db_error_raise(NULL, MI_EXCEPTION, "factorial: not enough memory"); case MI_DONE: /* At the end of the factorial recursion, the * function still needs to calculate: * value * factorial(value-1) */ retval *= value; break; } return retval; }
This code sample implements a factorial function. If the mi_call( ) function determines that there is sufficient stack space, the code recursively calls the handle_row( ) function to process the row value. The return value of the mi_call( ) function indicates whether mi_call( ) has allocated additional thread-stack memory, as follows.
The other mi_call( ) return values (MI_NOMEM and MI_TOOMANY) indicate error conditions. For these return values, the function uses the mi_db_error_raise( ) function to raise a database server exception and provide an error message.
The following CREATE FUNCTION registers the factorial( ) function:
CREATE FUNCTION factorial (INTEGER) RETURNS INTEGER EXTERNAL NAME "$INFORMIXDIR/extend/misc/fact_ius.bld" LANGUAGE C;
The following EXECUTE FUNCTION invokes the factorial( ) function:
EXECUTE FUNCTION factorial(5);Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]