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 ]