The "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 "extfnapiv3.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 UDAF // 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