This scalar UDF example checks the argument value pointer data to see if the input argument value is NULL. It also has an initialization function and a shutdown function, each of which can tolerate multiple calls.
#include "extfnapiv3.h"
#include <stdlib.h>
// A simple non-deterministic scalar UDF that adds
// an internal integer usage counter to its integer
// argument and then returns the resulting integer.
//
// Here, the start function creates a little structure for
// the counter, and then the finish function deallocates it.
//
// Corresponding SQL declaration:
//
// CREATE FUNCTION plus_counter(IN arg1 INT)
// RETURNS INT
// NOT DETERMINISTIC
// RESPECT NULL VALUES
// EXTERNAL NAME 'my_plus_counter@libudfex'
typedef struct my_counter {
a_sql_int32 _counter;
} my_counter;
#if defined __cplusplus
extern "C" {
#endif
static void my_plus_counter_start(a_v3_extfn_scalar_context *cntxt)
{
my_counter *cptr = (my_counter *)cntxt->_user_data;
// If we have not already allocated the
// counter structure, then do so now
if (!cptr) {
cptr = (my_counter *)malloc(sizeof(my_counter));
cntxt->_user_data = cptr;
}
cptr->_counter = 0;
}
static void my_plus_counter_finish(a_v3_extfn_scalar_context *cntxt)
{
// If we still have an allocated the
// counter structure, then free it now
if (cntxt->_user_data) {
free(cntxt->_user_data);
cntxt->_user_data = 0;
}
}
static void my_plus_counter_evaluate(a_v3_extfn_scalar_context *cntxt,
void *arg_handle)
{
an_extfn_value arg;
an_extfn_value outval;
a_sql_int32 arg1, result;
// Increment the usage counter
my_counter *cptr = (my_counter *)cntxt->_user_data;
cptr->_counter += 1;
// Get the one argument
(void) cntxt->get_value( arg_handle, 1, &arg );
if (!arg.data) {
// argument value was NULL;
arg1 = 0;
} else {
arg1 = *((a_sql_int32 *)arg.data);
}
outval.type = DT_INT;
outval.piece_len = sizeof(a_sql_int32);
result = arg1 + cptr->_counter;
outval.data = &result;
cntxt->set_value( arg_handle, &outval, 0 );
}
static a_v3_extfn_scalar my_plus_counter_descriptor =
{ &my_plus_counter_start,
&my_plus_counter_finish,
&my_plus_counter_evaluate,
NULL, // Reserved - initialize to NULL
NULL, // Reserved - initialize to NULL
NULL, // Reserved - initialize to NULL
NULL, // Reserved - initialize to NULL
NULL, // Reserved - initialize to NULL
NULL, // _for_server_internal_use
};
a_v3_extfn_scalar *my_plus_counter()
{
return &my_plus_counter_descriptor;
}
#if defined __cplusplus
}
#endif