Example C iterator function
To write an iterator C function, you use DataBlade® API functions, such as mi_fp_request(), mi_fp_setfuncstate(), mi_fp_setisdone(), and so on, with the MI_FPARAM data structure.
A C UDR can return only one value; therefore, there can be only one column in the virtual column list in the FROM clause. However, a C UDR can return a row type, which can capture multiple return values as a unit.
The following example demonstrates how to write a C iterator function and use it in the FROM clause; relevant DataBlade API and iterator states are highlighted.
create function fibseries(int x)
returns int with (handlesnulls,iterator, parallelizable)
external name "$USERFUNCDIR/fib.so"
language c;
/* A Function to return a set of integer. This function takes
stop val as a parameter and returns a fibonaucci series up to
stop val.
* Three states of fparam :
*
* SET_INIT: Allocate the function state structure defined.
This State Structure is allocated in PER_COMMAND duration to
hold the memory till the end of the command.
Make the fparam structure point to the State Structure.
Set the first two numbers of the series i.e 0 and 1; And
set the stop val field of State Structure to the stop val passed
to the function.
* SET_RETONE: Computes the next number in the series. Compares
it with the stop val to check if the exit criteria is met.
num1 = num2;num2 = next number in the series.
* SET_END: Frees the user Allocated Func State structure.
*/
#include <milib.h>
typedef struct fibState1 {
mi_integer fib_prec1;
mi_integer fib_prec2;
mi_integer fib_ncomputed;
mi_integer fib_endval;
}fibState;
mi_integer
fibseries(endval,fparam)
mi_integer endval;
MI_FPARAM *fparam;
{
fibState *fibstate;
mi_integer next;
switch(mi_fp_request(fparam)) {
case SET_INIT :
fibstate = (fibState *) mi_dalloc
(sizeof(fibState),PER_COMMAND);
mi_fp_setfuncstate(fparam,(void *)fibstate);
if (mi_fp_argisnull(fparam,0) || endval < 0) {
mi_fp_setreturnisnull(fparam,0,1);
break;
}
if (endval < 1) {
fibstate->fib_prec1 = 0;
fibstate->fib_prec2 = 1;
fibstate->fib_ncomputed = 1;
fibstate->fib_endval = endval;
}
else {
fibstate->fib_prec1 = 0;
fibstate->fib_prec2 = 1;
fibstate->fib_ncomputed = 0;
fibstate->fib_endval = endval;
}
break;
case SET_RETONE :
fibstate = mi_fp_funcstate(fparam);
if (fibstate->fib_ncomputed < 2) {
return((fibstate->fib_ncomputed++ == 0) ? 0 : 1);
}
next = fibstate->fib_prec1 + fibstate->fib_prec2;
if (next > fibstate->fib_endval) {
mi_fp_setisdone(fparam,1);
return 0;
}
if (next == 0) {
fibstate->fib_prec1 = 0;
fibstate->fib_prec1 = 1;
}
else {
fibstate->fib_prec1 = fibstate->fib_prec2;
fibstate->fib_prec2 = next;
}
return (next);
case SET_END :
fibstate = mi_fp_funcstate(fparam);
mi_free(fibstate);
break;
}
}
select vcol1 from table (function fibseries(100)) vtab1(vcol1);