Trait udf::AggregateUdf
source · 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:
init
is called once per result set (same as non-aggregate)clear
is called once per group within the result set, and should reset your structadd
is called once per row in the group, and should add the current row to the struct as neededprocess
is 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 (Henceerror
being 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