The aggregate UDF my_bit_or example is similar to the SA built-in BIT_OR, except my_bit_or operates only on unsigned integers, and can be used only as a simple aggregate.
The my_bit_or definition is somewhat simpler than the my_bit_xor example.
#include "extfnapiv4.h"
#include <stdlib.h>
#include <assert.h>
// A simple (non-OLAP) aggregate UDF that ORs a set
// of unsigned integer arguments, and whenever asked
// returns the resulting unsigned integer result.
//
// The start function creates a little structure for
// the running result, and the finish function then
// deallocates it.
//
// The aggregate usage restrictions for this aggregate UDF
// only allow its use as a simple aggregate, so the
// corresponding SQL declaration will look like:
//
// CREATE AGGREGATE FUNCTION my_bit_or(IN arg1 UNSIGNED INT)
// RETURNS UNSIGNED INT
// ON EMPTY INPUT RETURNS NULL
// OVER NOT ALLOWED
// EXTERNAL NAME 'my_bit_or@libudfex'
typedef struct my_or_result {
a_sql_uint32 _or_result;
a_sql_uint32 _non_null_seen;
} my_or_result;
#if defined __cplusplus
extern "C" {
#endif
static void my_or_start(a_v3_extfn_aggregate_context *cntxt)
{
}
static void my_or_finish(a_v3_extfn_aggregate_context *cntxt)
{
}
static void my_or_reset(a_v3_extfn_aggregate_context *cntxt)
{
my_or_result *cptr = (my_or_result *)cntxt->_user_calculation_context;
cptr->_or_result = 0;
cptr->_non_null_seen = 0;
}
static void my_or_next_value(a_v3_extfn_aggregate_context *cntxt,
void *arg_handle)
{
an_extfn_value arg;
a_sql_uint32 arg1;
my_or_result *cptr = (my_or_result *)cntxt->_user_calculation_context;
// Get the one argument, and add it to the total
if (cntxt->get_value( arg_handle, 1, &arg ) && arg.data)
{
arg1 = *((a_sql_uint32 *)arg.data);
cptr->_or_result |= arg1;
cptr->_non_null_seen = 1;
}
}
static void my_or_evaluate(a_v3_extfn_aggregate_context *cntxt,
void *arg_handle)
{
an_extfn_value outval;
my_or_result *cptr = (my_or_result *)cntxt->_user_calculation_context;
outval.type = DT_UNSINT;
outval.piece_len = sizeof(a_sql_uint32);
if (cptr->_non_null_seen)
{
outval.data = &cptr->_or_result;
}
else
{
// Return null if no values seen
outval.data = 0;
}
cntxt->set_value( arg_handle, &outval, 0 );
}
static a_v3_extfn_aggregate my_or_descriptor =
{
&my_or_start,
&my_or_finish,
&my_or_reset,
&my_or_next_value,
&my_or_evaluate,
NULL, // drop_val_extfn
NULL, // cume_eval,
NULL, // next_subaggregate_extfn
NULL, // drop_subaggregate_extfn
NULL, // evaluate_superaggregate_extfn
NULL, // reserved1_must_be_null
NULL, // reserved2_must_be_null
NULL, // reserved3_must_be_null
NULL, // reserved4_must_be_null
NULL, // reserved5_must_be_null
0, // indicators
( short )sizeof( my_or_result ), // context size
8, // context alignment
0.0, //external_bytes_per_group
0.0, // external bytes per row
0, // reserved6_must_be_null
0, // reserved7_must_be_null
0, // reserved8_must_be_null
0, // reserved9_must_be_null
0, // reserved10_must_be_null
NULL // _for_server_internal_use
};
extern "C"
a_v3_extfn_aggregate *my_bit_or()
{
return &my_or_descriptor;
}
#if defined __cplusplus
}
#endif