mod builtin_registry;
pub(crate) mod datetime;
pub(crate) mod logic;
pub(crate) mod math;
pub(crate) mod metadata;
pub(crate) mod string;
pub(crate) mod system;
pub(crate) mod udf;
pub(crate) mod vector;
use crate::ast::Expr;
use crate::catalog::Catalog;
use crate::error::DbError;
use crate::storage::Storage;
use crate::types::Value;
use super::aggregates::{dispatch_aggregate, is_aggregate_function};
use super::clock::Clock;
use super::context::ExecutionContext;
use super::model::ContextTable;
use super::string_norm::normalize_identifier;
use builtin_registry::{lookup_builtin_handler, lookup_system_variable};
pub(crate) fn eval_function(
name: &str,
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext<'_>,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if is_aggregate_function(name) {
if let Some(group) = ctx.current_group().clone() {
if let Some(res) = dispatch_aggregate(name, args, &group, ctx, catalog, storage, clock)
{
return res;
}
}
}
let upper = normalize_identifier(name);
let upper_str = upper.as_str();
if let Some(handler) = lookup_builtin_handler(upper_str) {
return handler(args, row, ctx, catalog, storage, clock);
}
if let Some(result) = lookup_system_variable(upper_str, ctx) {
return result;
}
match upper_str {
"COUNT" | "SUM" | "AVG" | "COUNT_BIG" => Err(DbError::Execution(format!(
"{} is only supported in grouped projection",
name
))),
"MIN" | "MAX" => Err(DbError::Execution(
"MIN/MAX require a FROM clause when used in scalar context (use in GROUP BY)".into(),
)),
_ => udf::eval_user_scalar_function(name, args, row, ctx, catalog, storage, clock),
}
}