The my_byte_length scalar UDF example computes the size of a column by streaming the data in piece by piece, then returns the size of the column in bytes.
#include "extfnapiv4.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
// A simple function that returns the size of a cell value in bytes
//
// CREATE FUNCTION my_byte_length(IN arg1 LONG BINARY)
// RETURNS UNSIGNED INT
// DETERMINISTIC
// IGNORE NULL VALUES
// EXTERNAL NAME 'my_byte_length@libudfex'
#if defined __cplusplus
extern "C" {
#endif
static void my_byte_length_evaluate(a_v3_extfn_scalar_context *cntxt,
void *arg_handle)
{
if (cntxt == NULL || arg_handle == NULL)
{
return;
}
an_extfn_value arg;
an_extfn_value outval;
a_sql_uint64 total_len;
// Get first argument
a_sql_uint32 fetchedLength = 0;
(void) cntxt->get_value( arg_handle, 1, &arg );
if (arg.data == NULL)
{
return;
}
fetchedLength += arg.piece_len;
// saving total length as it loses scope inside get_piece
total_len = arg.len.total_len;
while (fetchedLength < total_len)
{
(void) cntxt->get_piece( arg_handle, 1, &arg, fetchedLength );
fetchedLength += arg.piece_len;
}
//if this fails, the function did not get the full data from the cell
assert(fetchedLength == total_len);
outval.type = DT_UNSINT;
outval.piece_len = 4;
outval.data = &fetchedLength;
cntxt->set_value(arg_handle, &outval, 0);
}
static a_v3_extfn_scalar my_byte_length_descriptor = {
0,
0,
&my_byte_length_evaluate,
0, // Reserved - initialize to NULL
0, // Reserved - initialize to NULL
0, // Reserved - initialize to NULL
0, // Reserved - initialize to NULL
0, // Reserved - initialize to NULL
NULL // _for_server_internal_use
};
a_v3_extfn_scalar *my_byte_length()
{
return &my_byte_length_descriptor;
}
#if defined __cplusplus
}
#endif