use std::any::Any;
use std::fmt::Debug;
use anyhow::Result;
use super::Signature;
use crate::expr::Kind;
use crate::val::Value;
pub trait Accumulator: crate::exec::SendSyncRequirement + Debug {
fn update(&mut self, value: Value) -> Result<()>;
fn update_batch(&mut self, values: &[Value]) -> Result<()> {
for value in values {
self.update(value.clone())?;
}
Ok(())
}
#[allow(unused)]
fn merge(&mut self, other: Box<dyn Accumulator>) -> Result<()>;
fn finalize(&self) -> Result<Value>;
#[allow(unused)]
fn reset(&mut self);
#[allow(unused)]
fn clone_box(&self) -> Box<dyn Accumulator>;
#[allow(unused)]
fn as_any(&self) -> &dyn Any;
}
pub trait AggregateFunction: crate::exec::SendSyncRequirement + Debug {
fn name(&self) -> &'static str;
fn create_accumulator(&self) -> Box<dyn Accumulator>;
fn create_accumulator_with_args(&self, _args: &[Value]) -> Box<dyn Accumulator> {
self.create_accumulator()
}
#[allow(unused)]
fn signature(&self) -> Signature;
#[allow(unused)]
fn return_type(&self, _arg_types: &[Kind]) -> Result<Kind> {
Ok(self.signature().returns)
}
}
#[macro_export]
macro_rules! define_aggregate {
(
$struct_name:ident,
$func_name:literal,
($arg_name:ident : $arg_type:ident) -> $ret:ident,
$accumulator:ty
) => {
#[derive(Debug, Clone, Copy, Default)]
pub struct $struct_name;
impl $crate::exec::function::AggregateFunction for $struct_name {
fn name(&self) -> &'static str {
$func_name
}
fn create_accumulator(&self) -> Box<dyn $crate::exec::function::Accumulator> {
Box::new(<$accumulator>::default())
}
fn signature(&self) -> $crate::exec::function::Signature {
$crate::exec::function::Signature::new()
.arg(stringify!($arg_name), $crate::expr::Kind::$arg_type)
.returns($crate::expr::Kind::$ret)
}
}
};
(
$struct_name:ident,
$func_name:literal,
() -> $ret:ident,
$accumulator:ty
) => {
#[derive(Debug, Clone, Copy, Default)]
pub struct $struct_name;
impl $crate::exec::function::AggregateFunction for $struct_name {
fn name(&self) -> &'static str {
$func_name
}
fn create_accumulator(&self) -> Box<dyn $crate::exec::function::Accumulator> {
Box::new(<$accumulator>::default())
}
fn signature(&self) -> $crate::exec::function::Signature {
$crate::exec::function::Signature::new().returns($crate::expr::Kind::$ret)
}
}
};
}
#[macro_export]
macro_rules! register_aggregates {
($registry:expr, $($func:ty),* $(,)?) => {
$(
$registry.register_aggregate(<$func>::default());
)*
};
}