Skip to main content

akar_function/scalar/
mod.rs

1//! Scalar function evaluation.
2//!
3//! Each function takes input `Value` slices and produces an output `Value`.
4
5#![allow(
6    clippy::unnecessary_cast,
7    clippy::approx_constant,
8    clippy::manual_is_multiple_of,
9    clippy::clone_on_ref_ptr,
10    clippy::collapsible_if,
11    clippy::never_loop
12)]
13
14use crate::registry::*;
15use akar_common::types::Value;
16
17pub mod arithmetic;
18pub mod array;
19pub mod blob;
20pub mod boolean;
21pub mod cast;
22pub mod comparison;
23pub mod date;
24pub mod hash;
25pub mod interval;
26pub mod list;
27pub mod map_struct;
28pub mod path;
29pub mod schema;
30pub mod string;
31pub mod union_funcs;
32pub mod utility;
33pub mod utils;
34
35pub(crate) use arithmetic::{evaluate_arithmetic, numeric_to_f64};
36pub(crate) use array::evaluate_array;
37pub(crate) use blob::evaluate_blob;
38pub(crate) use boolean::evaluate_boolean;
39pub(crate) use cast::evaluate_cast;
40pub(crate) use comparison::evaluate_comparison;
41pub(crate) use date::evaluate_date;
42pub(crate) use hash::evaluate_hash;
43pub(crate) use interval::evaluate_interval;
44pub(crate) use list::evaluate_list;
45pub(crate) use map_struct::{evaluate_map, evaluate_struct};
46pub(crate) use path::{evaluate_path, evaluate_uuid};
47pub(crate) use schema::evaluate_schema;
48pub(crate) use string::{evaluate_string, get_string};
49pub(crate) use union_funcs::evaluate_union;
50pub(crate) use utility::evaluate_utility;
51pub use utils::set_rng_seed;
52pub(crate) use utils::*;
53
54// ==================== Module-level utilities ====================
55
56thread_local! {
57    pub(crate) static RNG_STATE: std::cell::Cell<u64> = std::cell::Cell::new(
58        std::time::SystemTime::now()
59            .duration_since(std::time::SystemTime::UNIX_EPOCH)
60            .map(|d| d.as_nanos() as u64)
61            .unwrap_or(12345)
62    );
63}
64
65/// Global regex cache — avoids recompiling regex patterns on every row.
66///
67/// Regex compilation is expensive (~10-50µs per pattern). For queries like
68/// `WHERE regex_matches(text, 'pattern')`, this saves the compilation cost
69/// for every row beyond the first.
70pub(crate) static REGEX_CACHE: std::sync::LazyLock<std::sync::Mutex<std::collections::HashMap<String, regex::Regex>>> =
71    std::sync::LazyLock::new(|| std::sync::Mutex::new(std::collections::HashMap::new()));
72
73pub fn evaluate_scalar(func: &ScalarFunction, args: &[Value]) -> Result<Value, String> {
74    match func {
75        ScalarFunction::Arithmetic { op } => evaluate_arithmetic(*op, args),
76        ScalarFunction::Comparison { op } => evaluate_comparison(*op, args),
77        ScalarFunction::String { op } => evaluate_string(*op, args),
78        ScalarFunction::Cast { target_type } => evaluate_cast(*target_type, args),
79        ScalarFunction::Date { op } => evaluate_date(*op, args),
80        ScalarFunction::List { op } => evaluate_list(*op, args),
81        ScalarFunction::Map { op } => evaluate_map(*op, args),
82        ScalarFunction::Struct { op } => evaluate_struct(*op, args),
83        ScalarFunction::Boolean { op } => evaluate_boolean(*op, args),
84        ScalarFunction::Utility { op } => evaluate_utility(*op, args),
85        ScalarFunction::Schema { op } => evaluate_schema(*op, args),
86        ScalarFunction::Array { op } => evaluate_array(*op, args),
87        ScalarFunction::Path { op } => evaluate_path(*op, args),
88        ScalarFunction::Hash { op } => evaluate_hash(*op, args),
89        ScalarFunction::Interval { op } => evaluate_interval(*op, args),
90        ScalarFunction::Blob { op } => evaluate_blob(*op, args),
91        ScalarFunction::Union { op } => evaluate_union(*op, args),
92        ScalarFunction::Uuid => evaluate_uuid(args),
93        ScalarFunction::CustomScalar { execute, .. } => (execute)(args),
94        ScalarFunction::SequenceOp { .. } => Err(
95            "Sequence operations (nextval/currval) require catalog access — handle at connection/processor level"
96                .into(),
97        ),
98    }
99}