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