common_function/
function_registry.rs1use std::collections::HashMap;
17use std::collections::hash_map::Entry;
18use std::sync::{Arc, LazyLock, RwLock};
19
20use datafusion::catalog::TableFunction;
21use datafusion_expr::expr_rewriter::FunctionRewrite;
22use datafusion_expr::{AggregateUDF, WindowUDF};
23
24use crate::admin::AdminFunction;
25use crate::aggrs::aggr_wrapper::StateMergeHelper;
26use crate::aggrs::approximate::ApproximateFunction;
27use crate::aggrs::count_hash::CountHash;
28use crate::aggrs::vector::VectorFunction as VectorAggrFunction;
29use crate::function::{Function, FunctionRef};
30use crate::function_factory::ScalarFunctionFactory;
31use crate::scalars::anomaly::AnomalyFunction;
32use crate::scalars::date::DateFunction;
33use crate::scalars::expression::ExpressionFunction;
34use crate::scalars::hll_count::HllCalcFunction;
35use crate::scalars::ip::IpFunctions;
36use crate::scalars::json::JsonFunction;
37use crate::scalars::matches::MatchesFunction;
38use crate::scalars::matches_term::MatchesTermFunction;
39use crate::scalars::math::MathFunction;
40use crate::scalars::primary_key::DecodePrimaryKeyFunction;
41use crate::scalars::string::register_string_functions;
42use crate::scalars::timestamp::TimestampFunction;
43use crate::scalars::uddsketch_calc::UddSketchCalcFunction;
44use crate::scalars::uddsketch_rank::UddSketchRankFunction;
45use crate::scalars::vector::VectorFunction as VectorScalarFunction;
46use crate::scalars::welford_stddev::WelfordStddevFunction;
47use crate::system::SystemFunction;
48
49#[derive(Default)]
50pub struct FunctionRegistry {
51 functions: RwLock<HashMap<String, ScalarFunctionFactory>>,
52 aggregate_functions: RwLock<HashMap<String, AggregateUDF>>,
53 table_functions: RwLock<HashMap<String, Arc<TableFunction>>>,
54 function_rewrites: RwLock<Vec<Arc<dyn FunctionRewrite + Send + Sync>>>,
55 window_functions: RwLock<HashMap<String, WindowUDF>>,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum FunctionRegistrationResult {
61 Registered,
63 AlreadyExists,
65}
66
67impl FunctionRegistry {
68 pub fn register(&self, func: impl Into<ScalarFunctionFactory>) {
77 let func = func.into();
78 let _ = self
79 .functions
80 .write()
81 .unwrap()
82 .insert(func.name().to_string(), func);
83 }
84
85 pub fn register_if_absent(
94 &self,
95 func: impl Into<ScalarFunctionFactory>,
96 ) -> FunctionRegistrationResult {
97 let func = func.into();
98 let mut functions = self.functions.write().unwrap();
99 match functions.entry(func.name().to_string()) {
100 Entry::Occupied(_) => FunctionRegistrationResult::AlreadyExists,
101 Entry::Vacant(entry) => {
102 entry.insert(func);
103 FunctionRegistrationResult::Registered
104 }
105 }
106 }
107
108 pub fn register_scalar(&self, func: impl Function + 'static) {
110 let func = Arc::new(func) as FunctionRef;
111
112 for alias in func.aliases() {
113 let func: ScalarFunctionFactory = func.clone().into();
114 let alias = ScalarFunctionFactory {
115 name: alias.clone(),
116 ..func
117 };
118 self.register(alias);
119 }
120
121 self.register(func)
122 }
123
124 pub fn register_aggr(&self, func: AggregateUDF) {
126 let _ = self
127 .aggregate_functions
128 .write()
129 .unwrap()
130 .insert(func.name().to_string(), func);
131 }
132
133 pub fn register_table_function(&self, func: TableFunction) {
135 let _ = self
136 .table_functions
137 .write()
138 .unwrap()
139 .insert(func.name().to_string(), Arc::new(func));
140 }
141
142 pub fn register_function_rewrite(&self, func: impl FunctionRewrite + Send + Sync + 'static) {
144 self.function_rewrites.write().unwrap().push(Arc::new(func));
145 }
146
147 pub fn register_window(&self, func: WindowUDF) {
149 let _ = self
150 .window_functions
151 .write()
152 .unwrap()
153 .insert(func.name().to_string(), func);
154 }
155
156 pub fn get_function(&self, name: &str) -> Option<ScalarFunctionFactory> {
157 self.functions.read().unwrap().get(name).cloned()
158 }
159
160 pub fn scalar_functions(&self) -> Vec<ScalarFunctionFactory> {
162 self.functions.read().unwrap().values().cloned().collect()
163 }
164
165 pub fn aggregate_functions(&self) -> Vec<AggregateUDF> {
167 self.aggregate_functions
168 .read()
169 .unwrap()
170 .values()
171 .cloned()
172 .collect()
173 }
174
175 pub fn table_functions(&self) -> Vec<Arc<TableFunction>> {
176 self.table_functions
177 .read()
178 .unwrap()
179 .values()
180 .cloned()
181 .collect()
182 }
183
184 pub fn window_functions(&self) -> Vec<WindowUDF> {
186 self.window_functions
187 .read()
188 .unwrap()
189 .values()
190 .cloned()
191 .collect()
192 }
193
194 pub fn is_aggr_func_exist(&self, name: &str) -> bool {
196 self.aggregate_functions.read().unwrap().contains_key(name)
197 }
198
199 pub fn function_rewrites(&self) -> Vec<Arc<dyn FunctionRewrite + Send + Sync>> {
201 self.function_rewrites.read().unwrap().clone()
202 }
203}
204
205pub static FUNCTION_REGISTRY: LazyLock<Arc<FunctionRegistry>> = LazyLock::new(|| {
206 let function_registry = FunctionRegistry::default();
207
208 MathFunction::register(&function_registry);
210 TimestampFunction::register(&function_registry);
211 DateFunction::register(&function_registry);
212 ExpressionFunction::register(&function_registry);
213 UddSketchCalcFunction::register(&function_registry);
214 UddSketchRankFunction::register(&function_registry);
215 HllCalcFunction::register(&function_registry);
216 WelfordStddevFunction::register(&function_registry);
217 DecodePrimaryKeyFunction::register(&function_registry);
218
219 MatchesFunction::register(&function_registry);
221 MatchesTermFunction::register(&function_registry);
222
223 SystemFunction::register(&function_registry);
225 AdminFunction::register(&function_registry);
226
227 JsonFunction::register(&function_registry);
229
230 register_string_functions(&function_registry);
232
233 VectorScalarFunction::register(&function_registry);
235 VectorAggrFunction::register(&function_registry);
236
237 #[cfg(feature = "geo")]
239 crate::scalars::geo::GeoFunctions::register(&function_registry);
240 #[cfg(feature = "geo")]
241 crate::aggrs::geo::GeoFunction::register(&function_registry);
242
243 IpFunctions::register(&function_registry);
245
246 ApproximateFunction::register(&function_registry);
248
249 CountHash::register(&function_registry);
251
252 StateMergeHelper::register(&function_registry);
254
255 AnomalyFunction::register(&function_registry);
257
258 Arc::new(function_registry)
259});
260
261static ADMIN_FUNCTION_REGISTRY: LazyLock<FunctionRegistry> = LazyLock::new(|| {
262 let registry = FunctionRegistry::default();
263 AdminFunction::register_admin_only(®istry);
264 registry
265});
266
267pub fn get_admin_function(name: &str) -> Option<ScalarFunctionFactory> {
269 ADMIN_FUNCTION_REGISTRY.get_function(name)
270}
271
272pub fn register_admin_function(
289 func: impl Into<ScalarFunctionFactory>,
290) -> FunctionRegistrationResult {
291 register_admin_function_in(&ADMIN_FUNCTION_REGISTRY, &FUNCTION_REGISTRY, func)
292}
293
294fn register_admin_function_in(
311 admin_registry: &FunctionRegistry,
312 normal_registry: &FunctionRegistry,
313 func: impl Into<ScalarFunctionFactory>,
314) -> FunctionRegistrationResult {
315 let func = func.into();
316 let mut admin_functions = admin_registry.functions.write().unwrap();
317 let normal_functions = normal_registry.functions.read().unwrap();
323 if normal_functions.contains_key(func.name()) {
324 drop(normal_functions);
325 return FunctionRegistrationResult::AlreadyExists;
326 }
327 let result = match admin_functions.entry(func.name().to_string()) {
328 Entry::Occupied(_) => FunctionRegistrationResult::AlreadyExists,
329 Entry::Vacant(entry) => {
330 entry.insert(func);
331 FunctionRegistrationResult::Registered
332 }
333 };
334 drop(normal_functions);
337 result
338}
339
340#[cfg(test)]
341mod tests {
342 use std::sync::{Arc, Barrier};
343 use std::thread;
344
345 use super::*;
346 use crate::scalars::test::TestAndFunction;
347 use crate::scalars::udf::create_udf;
348
349 fn named_factory(name: &str) -> ScalarFunctionFactory {
353 ScalarFunctionFactory {
354 name: name.to_string(),
355 factory: Arc::new(|_ctx| create_udf(Arc::new(TestAndFunction::default()))),
356 }
357 }
358
359 #[test]
360 fn test_function_registry() {
361 let registry = FunctionRegistry::default();
362
363 assert!(registry.get_function("test_and").is_none());
364 assert!(registry.scalar_functions().is_empty());
365 registry.register_scalar(TestAndFunction::default());
366 let _ = registry.get_function("test_and").unwrap();
367 assert_eq!(1, registry.scalar_functions().len());
368 }
369
370 #[test]
371 fn test_uddsketch_rank_registered() {
372 assert!(FUNCTION_REGISTRY.get_function("uddsketch_rank").is_some());
373 }
374
375 #[test]
376 fn test_register_if_absent_registers_new_function() {
377 let registry = FunctionRegistry::default();
378 let name = "pr3_register_if_absent_new";
379 let factory = named_factory(name);
380
381 assert_eq!(
382 registry.register_if_absent(factory.clone()),
383 FunctionRegistrationResult::Registered
384 );
385 let registered = registry
386 .get_function(name)
387 .expect("function should be registered");
388 assert!(Arc::ptr_eq(®istered.factory, &factory.factory));
389 }
390
391 #[test]
392 fn test_register_if_absent_first_registration_wins() {
393 let registry = FunctionRegistry::default();
394 let name = "pr3_register_if_absent_duplicate";
395 let first = named_factory(name);
396 let second = named_factory(name);
397
398 assert_eq!(
399 registry.register_if_absent(first.clone()),
400 FunctionRegistrationResult::Registered
401 );
402 assert_eq!(
403 registry.register_if_absent(second.clone()),
404 FunctionRegistrationResult::AlreadyExists
405 );
406
407 let stored = registry
408 .get_function(name)
409 .expect("function should be registered");
410 assert!(Arc::ptr_eq(&stored.factory, &first.factory));
411 assert!(!Arc::ptr_eq(&stored.factory, &second.factory));
412 }
413
414 #[test]
415 fn test_register_replaces_existing_function() {
416 let registry = FunctionRegistry::default();
418 let name = "pr3_register_replaces";
419 let first = named_factory(name);
420 let second = named_factory(name);
421
422 registry.register(first.clone());
423 registry.register(second.clone());
424
425 let stored = registry
426 .get_function(name)
427 .expect("function should be registered");
428 assert!(Arc::ptr_eq(&stored.factory, &second.factory));
429 assert!(!Arc::ptr_eq(&stored.factory, &first.factory));
430 }
431
432 #[test]
433 fn test_concurrent_register_if_absent_same_name() {
434 const THREADS: usize = 8;
435 let registry = Arc::new(FunctionRegistry::default());
436 let name = "pr3_concurrent_same_name";
437 let barrier = Arc::new(Barrier::new(THREADS));
438
439 let handles: Vec<_> = (0..THREADS)
440 .map(|_| {
441 let registry = Arc::clone(®istry);
442 let barrier = Arc::clone(&barrier);
443 thread::spawn(move || {
444 let factory = named_factory(name);
445 barrier.wait();
448 let result = registry.register_if_absent(factory.clone());
449 (result, factory)
450 })
451 })
452 .collect();
453
454 let mut results: Vec<(FunctionRegistrationResult, ScalarFunctionFactory)> =
455 Vec::with_capacity(THREADS);
456 for handle in handles {
457 results.push(handle.join().expect("thread should not panic"));
458 }
459
460 let registered = results
461 .iter()
462 .filter(|(result, _)| *result == FunctionRegistrationResult::Registered)
463 .count();
464 let already_exists = results
465 .iter()
466 .filter(|(result, _)| *result == FunctionRegistrationResult::AlreadyExists)
467 .count();
468 assert_eq!(registered, 1);
469 assert_eq!(already_exists, THREADS - 1);
470
471 let winner = results
472 .iter()
473 .find(|(result, _)| *result == FunctionRegistrationResult::Registered)
474 .map(|(_, factory)| factory)
475 .expect("exactly one registration must win");
476
477 let stored = registry
478 .get_function(name)
479 .expect("function should be registered");
480 assert!(
481 Arc::ptr_eq(&stored.factory, &winner.factory),
482 "the stored factory must be the factory of the winning registration"
483 );
484 }
485
486 #[test]
487 fn test_register_admin_function_first_wins() {
488 let name = "pr3_admin_runtime_register";
490 let first = named_factory(name);
491 let second = named_factory(name);
492
493 assert_eq!(
494 register_admin_function(first.clone()),
495 FunctionRegistrationResult::Registered
496 );
497 assert_eq!(
498 register_admin_function(second.clone()),
499 FunctionRegistrationResult::AlreadyExists
500 );
501
502 let stored = get_admin_function(name).expect("admin function should be queryable");
503 assert!(Arc::ptr_eq(&stored.factory, &first.factory));
504 assert!(!Arc::ptr_eq(&stored.factory, &second.factory));
505 }
506
507 #[test]
508 fn test_register_admin_function_duplicate_same_factory() {
509 let name = "pr3_admin_runtime_register_same_factory";
514 let factory = named_factory(name);
515
516 assert_eq!(
517 register_admin_function(factory.clone()),
518 FunctionRegistrationResult::Registered
519 );
520 assert_eq!(
521 register_admin_function(factory.clone()),
522 FunctionRegistrationResult::AlreadyExists
523 );
524
525 let stored = get_admin_function(name).expect("admin function should be queryable");
526 assert!(Arc::ptr_eq(&stored.factory, &factory.factory));
527 }
528
529 #[test]
530 fn test_register_admin_function_in_is_one_way_later_normal_register_allowed() {
531 let admin = FunctionRegistry::default();
536 let normal = FunctionRegistry::default();
537 let name = "pr3_admin_in_one_way";
538 let admin_factory = named_factory(name);
539 let normal_factory = named_factory(name);
540
541 assert_eq!(
542 register_admin_function_in(&admin, &normal, admin_factory.clone()),
543 FunctionRegistrationResult::Registered
544 );
545
546 normal.register(normal_factory.clone());
547
548 let stored_admin = admin
549 .get_function(name)
550 .expect("the ADMIN registration must be kept");
551 assert!(Arc::ptr_eq(&stored_admin.factory, &admin_factory.factory));
552 let stored_normal = normal
553 .get_function(name)
554 .expect("the later normal registration must succeed");
555 assert!(Arc::ptr_eq(&stored_normal.factory, &normal_factory.factory));
556 }
557
558 #[test]
559 fn test_register_admin_function_rejects_normal_registry_builtin_name() {
560 let factory = named_factory("flush_table");
568
569 assert_eq!(
570 register_admin_function(factory.clone()),
571 FunctionRegistrationResult::AlreadyExists
572 );
573 assert!(
574 get_admin_function("flush_table").is_none(),
575 "a normal-registry built-in must not be shadowed into the ADMIN registry"
576 );
577 assert!(
578 FUNCTION_REGISTRY.get_function("flush_table").is_some(),
579 "the normal-registry built-in must remain registered"
580 );
581 }
582
583 #[test]
584 fn test_builtin_admin_functions_remain_queryable() {
585 #[cfg(feature = "enterprise")]
588 {
589 assert!(get_admin_function("purge_table").is_some());
590 }
591 #[cfg(not(feature = "enterprise"))]
592 {
593 assert!(get_admin_function("purge_table").is_none());
594 }
595 }
596}