Skip to main content

reifydb_routine/function/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4pub mod error;
5pub mod registry;
6
7pub mod blob;
8pub mod clock;
9pub mod date;
10pub mod datetime;
11pub mod duration;
12pub mod flow;
13pub mod identity;
14pub mod is;
15pub mod json;
16pub mod math;
17pub mod meta;
18pub mod rql;
19pub mod series;
20pub mod text;
21pub mod time;
22pub mod uuid;
23
24use std::sync::Arc;
25
26use error::FunctionError;
27use reifydb_core::value::column::{
28	Column,
29	columns::Columns,
30	data::ColumnData,
31	view::group_by::{GroupByView, GroupKey},
32};
33use reifydb_runtime::context::RuntimeContext;
34use reifydb_type::{
35	fragment::Fragment,
36	util::bitvec::BitVec,
37	value::{
38		identity::IdentityId,
39		r#type::{Type, input_types::InputTypes},
40	},
41};
42
43use crate::function::uuid::{v4::UuidV4, v7::UuidV7};
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
46pub enum FunctionCapability {
47	Scalar,
48	Aggregate,
49	Generator,
50}
51
52#[derive(Debug, Clone)]
53pub struct FunctionInfo {
54	pub name: String,
55	pub description: Option<String>,
56}
57
58impl FunctionInfo {
59	pub fn new(name: &str) -> Self {
60		Self {
61			name: name.to_string(),
62			description: None,
63		}
64	}
65}
66
67pub struct FunctionContext<'a> {
68	pub fragment: Fragment,
69	pub runtime_context: &'a RuntimeContext,
70	pub identity: IdentityId,
71	pub row_count: usize,
72}
73
74impl<'a> FunctionContext<'a> {
75	pub fn new(
76		fragment: Fragment,
77		runtime_context: &'a RuntimeContext,
78		identity: IdentityId,
79		row_count: usize,
80	) -> Self {
81		Self {
82			fragment,
83			runtime_context,
84			identity,
85			row_count,
86		}
87	}
88}
89
90pub trait Function: Send + Sync {
91	fn info(&self) -> &FunctionInfo;
92	fn capabilities(&self) -> &[FunctionCapability];
93
94	fn return_type(&self, input_types: &[Type]) -> Type;
95	fn accepted_types(&self) -> InputTypes {
96		InputTypes::any()
97	}
98
99	fn propagates_options(&self) -> bool {
100		true
101	}
102
103	fn execute(&self, ctx: &FunctionContext, args: &Columns) -> Result<Columns, FunctionError>;
104
105	/// Calls the function, automatically propagating Option columns if
106	/// `propagates_options()` returns true.
107	fn call(&self, ctx: &FunctionContext, args: &Columns) -> Result<Columns, FunctionError> {
108		if !self.propagates_options() {
109			return self.execute(ctx, args);
110		}
111
112		let has_option = args.iter().any(|c| matches!(c.data(), ColumnData::Option { .. }));
113		if !has_option {
114			return self.execute(ctx, args);
115		}
116
117		let mut combined_bv: Option<BitVec> = None;
118		let mut unwrapped = Vec::with_capacity(args.len());
119		for col in args.iter() {
120			let (inner, bv) = col.data().unwrap_option();
121			if let Some(bv) = bv {
122				combined_bv = Some(match combined_bv {
123					Some(existing) => existing.and(bv),
124					None => bv.clone(),
125				});
126			}
127			unwrapped.push(Column::new(col.name().clone(), inner.clone()));
128		}
129
130		// Short-circuit: when all combined values are None, skip the inner function
131		// call entirely to avoid type-validation errors on placeholder inner types.
132		if let Some(ref bv) = combined_bv
133			&& bv.count_ones() == 0
134		{
135			let row_count = args.row_count();
136			let input_types: Vec<Type> = unwrapped.iter().map(|c| c.data.get_type()).collect();
137			let result_type = self.return_type(&input_types);
138			let result_data = ColumnData::none_typed(result_type, row_count);
139			return Ok(Columns::new(vec![Column::new(ctx.fragment.clone(), result_data)]));
140		}
141
142		let unwrapped_args = Columns::new(unwrapped);
143		let result = self.execute(ctx, &unwrapped_args)?;
144
145		match combined_bv {
146			Some(bv) => {
147				let wrapped_cols: Vec<Column> = result
148					.into_iter()
149					.map(|col| {
150						Column::new(
151							col.name,
152							ColumnData::Option {
153								inner: Box::new(col.data),
154								bitvec: bv.clone(),
155							},
156						)
157					})
158					.collect();
159				Ok(Columns::new(wrapped_cols))
160			}
161			None => Ok(result),
162		}
163	}
164
165	fn accumulator(&self, _ctx: &FunctionContext) -> Option<Box<dyn Accumulator>> {
166		None
167	}
168}
169
170pub trait Accumulator: Send + Sync {
171	fn update(&mut self, args: &Columns, groups: &GroupByView) -> Result<(), FunctionError>;
172	fn finalize(&mut self) -> Result<(Vec<GroupKey>, ColumnData), FunctionError>;
173}
174
175pub fn default_functions() -> registry::FunctionsConfigurator {
176	registry::Functions::builder()
177		.register_function(Arc::new(math::sum::Sum::new()))
178		.register_function(Arc::new(math::avg::Avg::new()))
179		.register_function(Arc::new(math::count::Count::new()))
180		.register_function(Arc::new(math::min::Min::new()))
181		.register_function(Arc::new(math::max::Max::new()))
182		.register_function(Arc::new(math::abs::Abs::new()))
183		.register_function(Arc::new(flow::to_json::FlowNodeToJson::new()))
184		.register_function(Arc::new(clock::now::Now::new()))
185		.register_function(Arc::new(blob::b58::BlobB58::new()))
186		.register_function(Arc::new(blob::b64::BlobB64::new()))
187		.register_function(Arc::new(blob::b64url::BlobB64url::new()))
188		.register_function(Arc::new(blob::hex::BlobHex::new()))
189		.register_function(Arc::new(blob::utf8::BlobUtf8::new()))
190		.register_function(Arc::new(math::acos::Acos::new()))
191		.register_function(Arc::new(math::asin::Asin::new()))
192		.register_function(Arc::new(math::atan::Atan::new()))
193		.register_function(Arc::new(math::atan2::Atan2::new()))
194		.register_function(Arc::new(math::ceil::Ceil::new()))
195		.register_function(Arc::new(math::clamp::Clamp::new()))
196		.register_function(Arc::new(math::cos::Cos::new()))
197		.register_function(Arc::new(math::euler::Euler::new()))
198		.register_function(Arc::new(math::exp::Exp::new()))
199		.register_function(Arc::new(math::floor::Floor::new()))
200		.register_function(Arc::new(math::gcd::Gcd::new()))
201		.register_function(Arc::new(math::lcm::Lcm::new()))
202		.register_function(Arc::new(math::log::Log::new()))
203		.register_function(Arc::new(math::log10::Log10::new()))
204		.register_function(Arc::new(math::log2::Log2::new()))
205		.register_function(Arc::new(math::modulo::Modulo::new()))
206		.register_function(Arc::new(math::pi::Pi::new()))
207		.register_function(Arc::new(math::power::Power::new()))
208		.register_function(Arc::new(math::round::Round::new()))
209		.register_function(Arc::new(math::sign::Sign::new()))
210		.register_function(Arc::new(math::sin::Sin::new()))
211		.register_function(Arc::new(math::sqrt::Sqrt::new()))
212		.register_function(Arc::new(math::tan::Tan::new()))
213		.register_function(Arc::new(math::truncate::Truncate::new()))
214		.register_function(Arc::new(date::year::DateYear::new()))
215		.register_function(Arc::new(date::month::DateMonth::new()))
216		.register_function(Arc::new(date::day::DateDay::new()))
217		.register_function(Arc::new(date::day_of_year::DateDayOfYear::new()))
218		.register_function(Arc::new(date::day_of_week::DateDayOfWeek::new()))
219		.register_function(Arc::new(date::quarter::DateQuarter::new()))
220		.register_function(Arc::new(date::week::DateWeek::new()))
221		.register_function(Arc::new(date::is_leap_year::DateIsLeapYear::new()))
222		.register_function(Arc::new(date::days_in_month::DateDaysInMonth::new()))
223		.register_function(Arc::new(date::end_of_month::DateEndOfMonth::new()))
224		.register_function(Arc::new(date::start_of_month::DateStartOfMonth::new()))
225		.register_function(Arc::new(date::start_of_year::DateStartOfYear::new()))
226		.register_function(Arc::new(date::new::DateNew::new()))
227		.register_function(Arc::new(date::now::DateNow::new()))
228		.register_function(Arc::new(date::add::DateAdd::new()))
229		.register_function(Arc::new(date::subtract::DateSubtract::new()))
230		.register_function(Arc::new(date::diff::DateDiff::new()))
231		.register_function(Arc::new(date::trunc::DateTrunc::new()))
232		.register_function(Arc::new(date::age::DateAge::new()))
233		.register_function(Arc::new(date::format::DateFormat::new()))
234		.register_function(Arc::new(time::hour::TimeHour::new()))
235		.register_function(Arc::new(time::minute::TimeMinute::new()))
236		.register_function(Arc::new(time::second::TimeSecond::new()))
237		.register_function(Arc::new(time::nanosecond::TimeNanosecond::new()))
238		.register_function(Arc::new(time::new::TimeNew::new()))
239		.register_function(Arc::new(time::now::TimeNow::new()))
240		.register_function(Arc::new(time::add::TimeAdd::new()))
241		.register_function(Arc::new(time::subtract::TimeSubtract::new()))
242		.register_function(Arc::new(time::diff::TimeDiff::new()))
243		.register_function(Arc::new(time::trunc::TimeTrunc::new()))
244		.register_function(Arc::new(time::age::TimeAge::new()))
245		.register_function(Arc::new(time::format::TimeFormat::new()))
246		.register_function(Arc::new(datetime::year::DateTimeYear::new()))
247		.register_function(Arc::new(datetime::month::DateTimeMonth::new()))
248		.register_function(Arc::new(datetime::day::DateTimeDay::new()))
249		.register_function(Arc::new(datetime::hour::DateTimeHour::new()))
250		.register_function(Arc::new(datetime::minute::DateTimeMinute::new()))
251		.register_function(Arc::new(datetime::second::DateTimeSecond::new()))
252		.register_function(Arc::new(datetime::nanosecond::DateTimeNanosecond::new()))
253		.register_function(Arc::new(datetime::day_of_year::DateTimeDayOfYear::new()))
254		.register_function(Arc::new(datetime::day_of_week::DateTimeDayOfWeek::new()))
255		.register_function(Arc::new(datetime::quarter::DateTimeQuarter::new()))
256		.register_function(Arc::new(datetime::week::DateTimeWeek::new()))
257		.register_function(Arc::new(datetime::date::DateTimeDate::new()))
258		.register_function(Arc::new(datetime::time::DateTimeTime::new()))
259		.register_function(Arc::new(datetime::epoch::DateTimeEpoch::new()))
260		.register_function(Arc::new(datetime::epoch_millis::DateTimeEpochMillis::new()))
261		.register_function(Arc::new(datetime::new::DateTimeNew::new()))
262		.register_function(Arc::new(datetime::now::DateTimeNow::new()))
263		.register_function(Arc::new(datetime::from_epoch::DateTimeFromEpoch::new()))
264		.register_function(Arc::new(datetime::from_epoch_millis::DateTimeFromEpochMillis::new()))
265		.register_function(Arc::new(datetime::add::DateTimeAdd::new()))
266		.register_function(Arc::new(datetime::subtract::DateTimeSubtract::new()))
267		.register_function(Arc::new(datetime::diff::DateTimeDiff::new()))
268		.register_function(Arc::new(datetime::trunc::DateTimeTrunc::new()))
269		.register_function(Arc::new(datetime::age::DateTimeAge::new()))
270		.register_function(Arc::new(datetime::format::DateTimeFormat::new()))
271		.register_function(Arc::new(duration::years::DurationYears::new()))
272		.register_function(Arc::new(duration::months::DurationMonths::new()))
273		.register_function(Arc::new(duration::weeks::DurationWeeks::new()))
274		.register_function(Arc::new(duration::days::DurationDays::new()))
275		.register_function(Arc::new(duration::hours::DurationHours::new()))
276		.register_function(Arc::new(duration::minutes::DurationMinutes::new()))
277		.register_function(Arc::new(duration::seconds::DurationSeconds::new()))
278		.register_function(Arc::new(duration::millis::DurationMillis::new()))
279		.register_function(Arc::new(duration::get_months::DurationGetMonths::new()))
280		.register_function(Arc::new(duration::get_days::DurationGetDays::new()))
281		.register_function(Arc::new(duration::get_nanos::DurationGetNanos::new()))
282		.register_function(Arc::new(duration::add::DurationAdd::new()))
283		.register_function(Arc::new(duration::subtract::DurationSubtract::new()))
284		.register_function(Arc::new(duration::negate::DurationNegate::new()))
285		.register_function(Arc::new(duration::scale::DurationScale::new()))
286		.register_function(Arc::new(duration::trunc::DurationTrunc::new()))
287		.register_function(Arc::new(duration::format::DurationFormat::new()))
288		.register_alias("duration::year", "duration::years")
289		.register_alias("duration::month", "duration::months")
290		.register_alias("duration::week", "duration::weeks")
291		.register_alias("duration::day", "duration::days")
292		.register_alias("duration::hour", "duration::hours")
293		.register_alias("duration::minute", "duration::minutes")
294		.register_alias("duration::second", "duration::seconds")
295		.register_function(Arc::new(text::ascii::TextAscii::new()))
296		.register_function(Arc::new(text::char::TextChar::new()))
297		.register_function(Arc::new(text::concat::TextConcat::new()))
298		.register_function(Arc::new(text::contains::TextContains::new()))
299		.register_function(Arc::new(text::count::TextCount::new()))
300		.register_function(Arc::new(text::ends_with::TextEndsWith::new()))
301		.register_function(Arc::new(text::index_of::TextIndexOf::new()))
302		.register_function(Arc::new(text::pad_left::TextPadLeft::new()))
303		.register_function(Arc::new(text::pad_right::TextPadRight::new()))
304		.register_function(Arc::new(text::repeat::TextRepeat::new()))
305		.register_function(Arc::new(text::replace::TextReplace::new()))
306		.register_function(Arc::new(text::reverse::TextReverse::new()))
307		.register_function(Arc::new(text::starts_with::TextStartsWith::new()))
308		.register_function(Arc::new(text::length::TextLength::new()))
309		.register_function(Arc::new(text::trim::TextTrim::new()))
310		.register_function(Arc::new(text::trim_end::TextTrimEnd::new()))
311		.register_function(Arc::new(text::trim_start::TextTrimStart::new()))
312		.register_function(Arc::new(text::upper::TextUpper::new()))
313		.register_function(Arc::new(text::lower::TextLower::new()))
314		.register_function(Arc::new(text::substring::TextSubstring::new()))
315		.register_function(Arc::new(text::format_bytes::FormatBytes::new()))
316		.register_function(Arc::new(text::format_bytes_si::FormatBytesSi::new()))
317		.register_function(Arc::new(meta::r#type::Type::new()))
318		.register_function(Arc::new(identity::id::Id::new()))
319		.register_function(Arc::new(is::some::IsSome::new()))
320		.register_function(Arc::new(is::none::IsNone::new()))
321		.register_function(Arc::new(is::r#type::IsType::new()))
322		.register_function(Arc::new(is::root::IsRoot::new()))
323		.register_function(Arc::new(is::anonymous::IsAnonymous::new()))
324		.register_function(Arc::new(json::object::JsonObject::new()))
325		.register_function(Arc::new(json::array::JsonArray::new()))
326		.register_function(Arc::new(json::pretty::JsonPretty::new()))
327		.register_function(Arc::new(json::serialize::JsonSerialize::new()))
328		.register_function(Arc::new(UuidV4::new()))
329		.register_function(Arc::new(UuidV7::new()))
330		.register_function(Arc::new(series::Series::new()))
331		.register_function(Arc::new(series::GenerateSeries::new()))
332		.register_function(Arc::new(rql::fingerprint::RqlFingerprint::new()))
333}