The aggregate UDF descriptor structure comprises serveral pieces:
typedef struct a_v3_extfn_aggregate – the metadata descriptor for an aggregate UDF function supplied by the library.
_start_extfn – required pointer to an initialization function for which the only argument is a pointer to a_v3_extfn_aggregate_context. Typically, used to allocate some structure and store its address in the _user_data field within the a_v3_extfn_aggregate_context. _start_extfn is only ever called once per a_v3_extfn_aggregate_context.
void (*_start_extfn)(a_v3_extfn_aggregate_context *);
_finish_extfn – required pointer to a shutdown function for which the only argument is a pointer to a_v3_extfn_aggregate_context. Typically, used to deallocate some structure with the address stored within the _user_data field in the a_v3_extfn_aggregate_context. _finish_extfn is only ever called once per a_v3_extfn_aggregate_context.
void (*_finish_extfn)(a_v3_extfn_aggregate_context *);
_reset_extfn – required pointer to a start-of-new-group function, for which the only argument is a pointer to a_v3_extfn_aggregate_context. Typically, used to reset some values in the structure for which the address was stashed within the _user_data field in the a_v3_extfn_aggregate_context. _reset_extfn is called repeatedly.
void (*_reset_extfn)(a_v3_extfn_aggregate_context *);
_next_value_extfn – required function pointer to be called for each new input set of argument values. The function does not set the result of the aggregation. Access to input argument values are through the get_value callback function and, if necessary, through repeated calls to the get_piece callback function, which is required only if piece_len is less than total_len.
void (*_next_value_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_evaluate_extfn – required function pointer to be called to return the resulting aggregate result value. _evaluate_extfn is sent to the server using the set_value callback function.
void (*_evaluate_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_drop_value_extfn – Optional function pointer that is called for each input set of argument values that has fallen out of a moving window frame. Do not use this function to set the result of the aggregation. Access to input argument values are through the get_value callback function and, if necessary, through repeated calls to the get_piece callback function; however, access is required only if piece_len is less than total_len. Set _drop_value_extfn to the null pointer if:
If this function is not supplied, and the user has specified a moving window, then each time the window frame moves, the reset function is called and each row now within the window is included by a call to the next_value function. Finally, the evaluate function is called.
However, if this function is supplied, each time the window frame moves, this drop_value function is called for each row falling out of the window frame, then the next_value function is called for each row that has just been added into the window frame. Finally, the evaluate function is called to produce the aggregate result.
void (*_drop_value_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_evaluate_cumulative_extfn – optional function pointer to be called for each new input set of argument values. If this function is supplied, and the usage is in a row-based window frame that spans UNBOUNDED PRECEDING to CURRENT ROW, then this function is called instead of next_value, immediately followed by calling evaluate. _evaluate_cumulative_extfn must set the result of the aggregation through the set_value callback. Access to input argument values are through the get_value callback function and, if necessary, through repeated calls to the get_piece callback function, which is only required if piece_len is less than total_len.
void (*_evaluate_cumulative_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_next_subaggregate_extfn – optional callback function pointer that, with the _evaluate_superaggregate_extfn function (and in some usages also with the _drop_subaggregate_extfn function), enables some usages of the aggregate to be optimized through parallel and partial results aggregation.
Some aggregates, when used as simple aggregates (in other words, not OLAP-style aggregates with an OVER clause) can be partitioned by first producing a set of intermediate aggregate results where each of the intermediate results is computed from a disjoint subset of the input rows. Examples of such partitionable aggregates include:
SUM, where the final SUM can be computed by performing a SUM for each disjoint subset of the input rows and then performing a SUM over the sub-SUMs; and
COUNT(*), where the final COUNT can be computed by performing a COUNT for each disjoint subset of the input rows and then performing a SUM over the COUNTs from each partition.
When an aggregate satisfies the above conditions, the server may choose to make the computation of that aggregate parallel. For aggregate UDFs, this optimization can be applied only if both the _next_subaggregate_extfn callback and the _evaluate_superaggregate_extfn callback are supplied. This usage pattern does not require _drop_subaggregate_extfn.
Similarly, if an aggregate can be used with a RANGE-based OVER clause, an optimization can be applied if _next_subaggregate_extfn, _drop_subaggregate_extfn, and _evaluate_superaggregate_extfn) functions are all supplied by the UDAF implementation.
_next_subaggregate_extfn does not set the final result of the aggregation, and by definition, has exactly one input argument value that is the same data type as the return value of the aggregate UDF. Access to the sub-aggregate input value is through the get_value callback function and, if necessary, through repeated calls to the get_piece callback function, which is required only if piece_len is less than total_len.
Direct communication between sub-aggregates and the super-aggregate is impossible; the server handles all such communication. The sub-aggregates and the super-aggregate do not share the context structure. Individual sub-aggregates are treated exactly the same as nonpartitioned aggregates. The independent super-aggregate sees a calling pattern that looks like this:
_start_extfn _reset_extfn _next_subaggregate_extfn (repeated 0 to N times) _evaluate_superaggregate_extfn _finish_extfn
void (*_next_subaggregate_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_drop_subaggregate_extfn – optional callback function pointer that, together with _next_subaggregate_extfn and _evaluate_superaggregate_extfn, enables some usages involving RANGE-based OVER clauses to be optimized through a partial aggregation. _drop_subaggregate_extfn is called whenever a set of rows sharing a common ordering key value have collectively fallen out of a moving window. This optimization is applied only if all three functions are provided by the UDF.
void (*_drop_subaggregate_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
_evaluate_superaggregate_extfn – optional callback function pointer that, together with _next_subaggregate_extfn (and in some cases also with _drop_subaggregate_extfn), enables some usages to be optimized by running in parallel.
_evaluate_superaggregate_extfn is called, as described above, when it is time to return the result of a partitioned aggregate. The result value is sent to the server using the set_value callback function from the a_v3_extfn_aggregate_context structure:
void (*_evaluate_superaggregate_extfn)(a_v3_extfn_aggregate_context *cntxt, void *args_handle);
NULL fields – initialize these fields to NULL:
void * reserved1_must_be_null; void * reserved2_must_be_null; void * reserved3_must_be_null; void * reserved4_must_be_null; void * reserved5_must_be_null;
Status indicator bit field – a bit field containing indicators that allow the engine to optimize the algorithm used to process the aggregate.
a_sql_uint32 indicators;
_calculation_context_size – the number of bytes for the server to allocate for each UDF calculation context. The server may allocate multiple calculation contexts during query processing. The currently active group context is available in a_v3_extfn_aggregate_context_user_calculation_context.
short _calculation_context_size;
_calculation_context_alignment – specifies the alignment requirement for the user's calculation context. Valid values include 1, 2, 4, or 8.
short _calculation_context_alignment;
External memory requirments – the following fields allow the optimizer to consider the cost of externally allocated memory. With these values, the optimizer can consider the degree to which multiple simultaneous calculations can be made. These counters should be estimates based on a typical row or group, and should not be maximum values. If no memory is allocated by the UDF, set these fields to zero.
external_bytes_per_group – The amount of memory allocated to a group at the start of each aggregate. Typically, any memory allocated during the reset() call.
external_bytes_per_row – The amount of memory allocated by the UDF for each row of a group. Typically, the amount of memory allocated during next_value().
double external_bytes_per_group; double external_bytes_per_row;
Reserved fields for future use – initialize these fields:
a_sql_uint64 reserved6_must_be_null; a_sql_uint64 reserved7_must_be_null; a_sql_uint64 reserved8_must_be_null; a_sql_uint64 reserved9_must_be_null; a_sql_uint64 reserved10_must_be_null;
Closing syntax – Complete the descriptor with this syntax:
//---------- For Server Internal Use Only ---------- void * _for_server_internal_use; } a_extfn_aggregate;