pub trait AggregateUdf: BasicUdf {
// Required methods
fn clear(
&mut self,
cfg: &UdfCfg<Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8>;
fn add(
&mut self,
cfg: &UdfCfg<Process>,
args: &ArgList<'_, Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8>;
// Provided method
fn remove(
&mut self,
cfg: &UdfCfg<Process>,
args: &ArgList<'_, Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8> { ... }
}Expand description
This trait must be implemented if this function performs aggregation.
The basics of aggregation are simple:
initis called once per result set (same as non-aggregate)clearis called once per group within the result set, and should reset your structaddis called once per row in the group, and should add the current row to the struct as neededprocessis called at the end of each group, and should produce the result value for that group
§Aggregate Error Handling
Error handling for aggregate functions is weird, and does not lend itself to easy understandability. The following is my best understanding of the process:
- Any aggregate function may set a nonzero error (Represented here in return
value by
Err(NonZeroU8)). The value is not important, can be something internal - These errors do not stop the remaining
add()/remove()functions from being called, but these functions do receive the error (and so may choose to do nothing if there is an error set) - Errors are not reset on
clear(); you must do this manually (Henceerrorbeing mutable in this function signature)
In order to enforce some of these constraints, we use NonZeroU8 to
represent error types (which has the nice side effect of being optimizable).
Unfortunately, it is somewhat cumbersome to use, e.g.: return Err(NonZeroU8::new(1).unwrap());
Required Methods§
Sourcefn clear(
&mut self,
cfg: &UdfCfg<Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8>
fn clear( &mut self, cfg: &UdfCfg<Process>, error: Option<NonZeroU8>, ) -> Result<(), NonZeroU8>
Clear is run once at the beginning of each aggregate group and should reset everything needed in the struct.
§Errors
The error arg provides the error value from the previous group, and
this function may choose to reset it (that is probably a good idea to
do). error will be None if there is currently no error.
To clear the error, simply return Ok(()).
Return an error if something goes wrong within this function, or if you would like to propegate the previous error.
Sourcefn add(
&mut self,
cfg: &UdfCfg<Process>,
args: &ArgList<'_, Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8>
fn add( &mut self, cfg: &UdfCfg<Process>, args: &ArgList<'_, Process>, error: Option<NonZeroU8>, ) -> Result<(), NonZeroU8>
Add an item to the aggregate
Usually this is implemented by adding something to an intemdiate value inside the core struct type.
§Errors
Hit a problem? Return an integer, which may or may not be meaningful to
you. This can be done with return Err(NonZeroU8::new(1).unwrap());.
The error argument tells you if there has been an error at some point,
and the return value also detemines whether to propegate/modify the
error (probably what you want) or clear it (I can’t think of any good
reason to do this in add()). If you would like to propegate the error
without action, just add the following as the first line of the
function:
error.map_or(Ok(()), Err)?;If you do this,
Provided Methods§
Sourcefn remove(
&mut self,
cfg: &UdfCfg<Process>,
args: &ArgList<'_, Process>,
error: Option<NonZeroU8>,
) -> Result<(), NonZeroU8>
fn remove( &mut self, cfg: &UdfCfg<Process>, args: &ArgList<'_, Process>, error: Option<NonZeroU8>, ) -> Result<(), NonZeroU8>
Remove only applies to MariaDB, for use with window functions; i.e.,
remove will be called on a row that should be removed from the current
set (has moved out of the window).
This is optional; a default is supplied so no action is needed. If you
would like to use remove, just reimplement it.
https://mariadb.com/kb/en/user-defined-functions-calling-sequences/#x_remove
§Errors
Errors are handled the same as with AggregateUdf::add(), see the
description there
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.