Skip to main content

common_function/
function_registry.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! functions registry
16use 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::extremum::Extremum;
29use crate::aggrs::vector::VectorFunction as VectorAggrFunction;
30use crate::function::{Function, FunctionRef};
31use crate::function_factory::ScalarFunctionFactory;
32#[cfg(feature = "ai_functions")]
33use crate::scalars::ai;
34use crate::scalars::anomaly::AnomalyFunction;
35use crate::scalars::avg_calc::AvgCalcFunction;
36use crate::scalars::date::DateFunction;
37use crate::scalars::expression::ExpressionFunction;
38use crate::scalars::hll_count::HllCalcFunction;
39use crate::scalars::ip::IpFunctions;
40use crate::scalars::json::JsonFunction;
41use crate::scalars::matches::MatchesFunction;
42use crate::scalars::matches_term::MatchesTermFunction;
43use crate::scalars::math::MathFunction;
44use crate::scalars::primary_key::DecodePrimaryKeyFunction;
45use crate::scalars::string::register_string_functions;
46use crate::scalars::timestamp::TimestampFunction;
47use crate::scalars::uddsketch_calc::UddSketchCalcFunction;
48use crate::scalars::uddsketch_rank::UddSketchRankFunction;
49use crate::scalars::vector::VectorFunction as VectorScalarFunction;
50use crate::scalars::welford_stddev::WelfordStddevFunction;
51use crate::system::SystemFunction;
52
53#[derive(Default)]
54pub struct FunctionRegistry {
55    functions: RwLock<HashMap<String, ScalarFunctionFactory>>,
56    aggregate_functions: RwLock<HashMap<String, AggregateUDF>>,
57    table_functions: RwLock<HashMap<String, Arc<TableFunction>>>,
58    function_rewrites: RwLock<Vec<Arc<dyn FunctionRewrite + Send + Sync>>>,
59    window_functions: RwLock<HashMap<String, WindowUDF>>,
60}
61
62/// The result of registering a function.
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum FunctionRegistrationResult {
65    /// The function was newly registered.
66    Registered,
67    /// A function with the same name was already registered and was kept.
68    AlreadyExists,
69}
70
71impl FunctionRegistry {
72    /// Register a function in the registry by converting it into a `ScalarFunctionFactory`.
73    ///
74    /// # Arguments
75    ///
76    /// * `func` - An object that can be converted into a `ScalarFunctionFactory`.
77    ///
78    /// The function is inserted into the internal function map, keyed by its name.
79    /// If a function with the same name already exists, it will be replaced.
80    pub fn register(&self, func: impl Into<ScalarFunctionFactory>) {
81        let func = func.into();
82        let _ = self
83            .functions
84            .write()
85            .unwrap()
86            .insert(func.name().to_string(), func);
87    }
88
89    /// Register a function only if no function with the same name exists.
90    ///
91    /// The duplicate check and the insert happen atomically under the same
92    /// write lock of the functions map. If a function with the same name
93    /// already exists, it is kept unchanged and
94    /// [`FunctionRegistrationResult::AlreadyExists`] is returned; otherwise the
95    /// function is registered and [`FunctionRegistrationResult::Registered`] is
96    /// returned.
97    pub fn register_if_absent(
98        &self,
99        func: impl Into<ScalarFunctionFactory>,
100    ) -> FunctionRegistrationResult {
101        let func = func.into();
102        let mut functions = self.functions.write().unwrap();
103        match functions.entry(func.name().to_string()) {
104            Entry::Occupied(_) => FunctionRegistrationResult::AlreadyExists,
105            Entry::Vacant(entry) => {
106                entry.insert(func);
107                FunctionRegistrationResult::Registered
108            }
109        }
110    }
111
112    /// Register a scalar function in the registry.
113    pub fn register_scalar(&self, func: impl Function + 'static) {
114        let func = Arc::new(func) as FunctionRef;
115
116        for alias in func.aliases() {
117            let func: ScalarFunctionFactory = func.clone().into();
118            let alias = ScalarFunctionFactory {
119                name: alias.clone(),
120                ..func
121            };
122            self.register(alias);
123        }
124
125        self.register(func)
126    }
127
128    /// Register an aggregate function in the registry.
129    pub fn register_aggr(&self, func: AggregateUDF) {
130        let _ = self
131            .aggregate_functions
132            .write()
133            .unwrap()
134            .insert(func.name().to_string(), func);
135    }
136
137    /// Register a table function
138    pub fn register_table_function(&self, func: TableFunction) {
139        let _ = self
140            .table_functions
141            .write()
142            .unwrap()
143            .insert(func.name().to_string(), Arc::new(func));
144    }
145
146    /// Register a function rewrite rule.
147    pub fn register_function_rewrite(&self, func: impl FunctionRewrite + Send + Sync + 'static) {
148        self.function_rewrites.write().unwrap().push(Arc::new(func));
149    }
150
151    /// Register a window function (UDWF).
152    pub fn register_window(&self, func: WindowUDF) {
153        let _ = self
154            .window_functions
155            .write()
156            .unwrap()
157            .insert(func.name().to_string(), func);
158    }
159
160    pub fn get_function(&self, name: &str) -> Option<ScalarFunctionFactory> {
161        self.functions.read().unwrap().get(name).cloned()
162    }
163
164    /// Returns a list of all scalar functions registered in the registry.
165    pub fn scalar_functions(&self) -> Vec<ScalarFunctionFactory> {
166        self.functions.read().unwrap().values().cloned().collect()
167    }
168
169    /// Returns a list of all aggregate functions registered in the registry.
170    pub fn aggregate_functions(&self) -> Vec<AggregateUDF> {
171        self.aggregate_functions
172            .read()
173            .unwrap()
174            .values()
175            .cloned()
176            .collect()
177    }
178
179    pub fn table_functions(&self) -> Vec<Arc<TableFunction>> {
180        self.table_functions
181            .read()
182            .unwrap()
183            .values()
184            .cloned()
185            .collect()
186    }
187
188    /// Returns a list of all window functions registered in the registry.
189    pub fn window_functions(&self) -> Vec<WindowUDF> {
190        self.window_functions
191            .read()
192            .unwrap()
193            .values()
194            .cloned()
195            .collect()
196    }
197
198    /// Returns a registered aggregate function by name.
199    pub fn get_aggr_func(&self, name: &str) -> Option<AggregateUDF> {
200        self.aggregate_functions.read().unwrap().get(name).cloned()
201    }
202
203    /// Returns true if an aggregate function with the given name exists in the registry.
204    pub fn is_aggr_func_exist(&self, name: &str) -> bool {
205        self.aggregate_functions.read().unwrap().contains_key(name)
206    }
207
208    /// Returns a list of all function rewrite rules registered in the registry.
209    pub fn function_rewrites(&self) -> Vec<Arc<dyn FunctionRewrite + Send + Sync>> {
210        self.function_rewrites.read().unwrap().clone()
211    }
212}
213
214pub static FUNCTION_REGISTRY: LazyLock<Arc<FunctionRegistry>> = LazyLock::new(|| {
215    let function_registry = FunctionRegistry::default();
216
217    // Utility functions
218    MathFunction::register(&function_registry);
219    TimestampFunction::register(&function_registry);
220    DateFunction::register(&function_registry);
221    ExpressionFunction::register(&function_registry);
222    AvgCalcFunction::register(&function_registry);
223    UddSketchCalcFunction::register(&function_registry);
224    UddSketchRankFunction::register(&function_registry);
225    HllCalcFunction::register(&function_registry);
226    WelfordStddevFunction::register(&function_registry);
227    DecodePrimaryKeyFunction::register(&function_registry);
228
229    // Full text search function
230    MatchesFunction::register(&function_registry);
231    MatchesTermFunction::register(&function_registry);
232    #[cfg(feature = "ai_functions")]
233    ai::register(&function_registry);
234
235    // System and administration functions
236    SystemFunction::register(&function_registry);
237    AdminFunction::register(&function_registry);
238
239    // Json related functions
240    JsonFunction::register(&function_registry);
241
242    // String related functions
243    register_string_functions(&function_registry);
244
245    // Vector related functions
246    VectorScalarFunction::register(&function_registry);
247    VectorAggrFunction::register(&function_registry);
248
249    // Geo functions
250    #[cfg(feature = "geo")]
251    crate::scalars::geo::GeoFunctions::register(&function_registry);
252    #[cfg(feature = "geo")]
253    crate::aggrs::geo::GeoFunction::register(&function_registry);
254
255    // Ip functions
256    IpFunctions::register(&function_registry);
257
258    // Approximate functions
259    ApproximateFunction::register(&function_registry);
260
261    // CountHash function
262    CountHash::register(&function_registry);
263
264    // PromQL min/max; registered before the state functions are derived.
265    Extremum::register(&function_registry);
266
267    // state function of supported aggregate functions
268    StateMergeHelper::register(&function_registry);
269
270    // Anomaly detection window functions
271    AnomalyFunction::register(&function_registry);
272
273    Arc::new(function_registry)
274});
275
276static ADMIN_FUNCTION_REGISTRY: LazyLock<FunctionRegistry> = LazyLock::new(|| {
277    let registry = FunctionRegistry::default();
278    AdminFunction::register_admin_only(&registry);
279    registry
280});
281
282/// Returns a function that is only available to the ADMIN statement executor.
283pub fn get_admin_function(name: &str) -> Option<ScalarFunctionFactory> {
284    ADMIN_FUNCTION_REGISTRY.get_function(name)
285}
286
287/// Register a function that is only available to the ADMIN statement executor.
288///
289/// If a function with the same name is already registered in the ADMIN
290/// registry, the existing one is kept and
291/// [`FunctionRegistrationResult::AlreadyExists`] is returned. A name that
292/// already exists in the normal [`FUNCTION_REGISTRY`] when this call
293/// linearizes is also rejected: the ADMIN executor resolves admin-only
294/// functions before falling back to the normal registry, so inserting such a
295/// name here would shadow the built-in. Otherwise the function is registered
296/// and [`FunctionRegistrationResult::Registered`] is returned.
297///
298/// The enforced contract is one-way: it only guards the ADMIN registration
299/// against names already present in the normal registry. A later ordinary
300/// [`FunctionRegistry::register`] may still install the same name in the
301/// normal registry because the normal registry keeps its legacy replace
302/// semantics.
303pub fn register_admin_function(
304    func: impl Into<ScalarFunctionFactory>,
305) -> FunctionRegistrationResult {
306    register_admin_function_in(&ADMIN_FUNCTION_REGISTRY, &FUNCTION_REGISTRY, func)
307}
308
309/// Core implementation of [`register_admin_function`] against a pair of
310/// registries, parameterized so tests can exercise it with local registries.
311///
312/// Locking: the ADMIN-registry write lock is acquired first, then a read lock
313/// on the normal registry, and the normal-registry guard (bound to
314/// `normal_functions`) is kept alive through both the normal-name check and
315/// the ADMIN insertion below. This is the only code path that holds both
316/// registries' locks, so the ADMIN -> FUNCTION acquisition order is
317/// consistent and a concurrent normal-registry registration cannot slip in
318/// between the check and the ADMIN insert and be shadowed.
319///
320/// The enforced contract is one-way: it only guards the ADMIN registration
321/// against names already present in the normal registry. A later ordinary
322/// [`FunctionRegistry::register`] may still install the same name in the
323/// normal registry because the normal registry keeps its legacy replace
324/// semantics.
325fn register_admin_function_in(
326    admin_registry: &FunctionRegistry,
327    normal_registry: &FunctionRegistry,
328    func: impl Into<ScalarFunctionFactory>,
329) -> FunctionRegistrationResult {
330    let func = func.into();
331    let mut admin_functions = admin_registry.functions.write().unwrap();
332    // The normal-registry guard is a read lock: it is held across the
333    // normal-name check and the ADMIN insertion below, and while it is alive
334    // no writer can acquire the normal-registry write lock, so a concurrent
335    // normal-registry registration cannot slip in between the check and the
336    // ADMIN insert and be shadowed.
337    let normal_functions = normal_registry.functions.read().unwrap();
338    if normal_functions.contains_key(func.name()) {
339        drop(normal_functions);
340        return FunctionRegistrationResult::AlreadyExists;
341    }
342    let result = match admin_functions.entry(func.name().to_string()) {
343        Entry::Occupied(_) => FunctionRegistrationResult::AlreadyExists,
344        Entry::Vacant(entry) => {
345            entry.insert(func);
346            FunctionRegistrationResult::Registered
347        }
348    };
349    // Drop the read guard only after the ADMIN insertion, so writers to the
350    // normal registry stay blocked until the check-and-insert is complete.
351    drop(normal_functions);
352    result
353}
354
355#[cfg(test)]
356mod tests {
357    use std::sync::{Arc, Barrier};
358    use std::thread;
359
360    use super::*;
361    use crate::scalars::test::TestAndFunction;
362    use crate::scalars::udf::create_udf;
363
364    /// Creates a [`ScalarFunctionFactory`] with the given name. Each call
365    /// allocates a distinct factory closure, so factories can be told apart by
366    /// [`Arc::ptr_eq`] on their `factory` field even when names are identical.
367    fn named_factory(name: &str) -> ScalarFunctionFactory {
368        ScalarFunctionFactory {
369            name: name.to_string(),
370            factory: Arc::new(|_ctx| create_udf(Arc::new(TestAndFunction::default()))),
371        }
372    }
373
374    #[test]
375    fn test_function_registry() {
376        let registry = FunctionRegistry::default();
377
378        assert!(registry.get_function("test_and").is_none());
379        assert!(registry.scalar_functions().is_empty());
380        registry.register_scalar(TestAndFunction::default());
381        let _ = registry.get_function("test_and").unwrap();
382        assert_eq!(1, registry.scalar_functions().len());
383    }
384
385    #[test]
386    fn test_uddsketch_rank_registered() {
387        assert!(FUNCTION_REGISTRY.get_function("uddsketch_rank").is_some());
388    }
389
390    #[test]
391    fn test_ai_registration_matches_feature() {
392        for name in ["ai_match", "ai_choose", "ai_score"] {
393            assert_eq!(
394                FUNCTION_REGISTRY.get_function(name).is_some(),
395                cfg!(feature = "ai_functions"),
396                "{name}"
397            );
398        }
399        for name in ["jev", "jev_choice", "jev_score"] {
400            assert!(FUNCTION_REGISTRY.get_function(name).is_none(), "{name}");
401        }
402    }
403
404    #[test]
405    fn test_register_if_absent_registers_new_function() {
406        let registry = FunctionRegistry::default();
407        let name = "pr3_register_if_absent_new";
408        let factory = named_factory(name);
409
410        assert_eq!(
411            registry.register_if_absent(factory.clone()),
412            FunctionRegistrationResult::Registered
413        );
414        let registered = registry
415            .get_function(name)
416            .expect("function should be registered");
417        assert!(Arc::ptr_eq(&registered.factory, &factory.factory));
418    }
419
420    #[test]
421    fn test_register_if_absent_first_registration_wins() {
422        let registry = FunctionRegistry::default();
423        let name = "pr3_register_if_absent_duplicate";
424        let first = named_factory(name);
425        let second = named_factory(name);
426
427        assert_eq!(
428            registry.register_if_absent(first.clone()),
429            FunctionRegistrationResult::Registered
430        );
431        assert_eq!(
432            registry.register_if_absent(second.clone()),
433            FunctionRegistrationResult::AlreadyExists
434        );
435
436        let stored = registry
437            .get_function(name)
438            .expect("function should be registered");
439        assert!(Arc::ptr_eq(&stored.factory, &first.factory));
440        assert!(!Arc::ptr_eq(&stored.factory, &second.factory));
441    }
442
443    #[test]
444    fn test_register_replaces_existing_function() {
445        // Regression test: `register` keeps its replace semantics.
446        let registry = FunctionRegistry::default();
447        let name = "pr3_register_replaces";
448        let first = named_factory(name);
449        let second = named_factory(name);
450
451        registry.register(first.clone());
452        registry.register(second.clone());
453
454        let stored = registry
455            .get_function(name)
456            .expect("function should be registered");
457        assert!(Arc::ptr_eq(&stored.factory, &second.factory));
458        assert!(!Arc::ptr_eq(&stored.factory, &first.factory));
459    }
460
461    #[test]
462    fn test_concurrent_register_if_absent_same_name() {
463        const THREADS: usize = 8;
464        let registry = Arc::new(FunctionRegistry::default());
465        let name = "pr3_concurrent_same_name";
466        let barrier = Arc::new(Barrier::new(THREADS));
467
468        let handles: Vec<_> = (0..THREADS)
469            .map(|_| {
470                let registry = Arc::clone(&registry);
471                let barrier = Arc::clone(&barrier);
472                thread::spawn(move || {
473                    let factory = named_factory(name);
474                    // Synchronize so every thread attempts registration at the
475                    // same time; only one may win the write lock.
476                    barrier.wait();
477                    let result = registry.register_if_absent(factory.clone());
478                    (result, factory)
479                })
480            })
481            .collect();
482
483        let mut results: Vec<(FunctionRegistrationResult, ScalarFunctionFactory)> =
484            Vec::with_capacity(THREADS);
485        for handle in handles {
486            results.push(handle.join().expect("thread should not panic"));
487        }
488
489        let registered = results
490            .iter()
491            .filter(|(result, _)| *result == FunctionRegistrationResult::Registered)
492            .count();
493        let already_exists = results
494            .iter()
495            .filter(|(result, _)| *result == FunctionRegistrationResult::AlreadyExists)
496            .count();
497        assert_eq!(registered, 1);
498        assert_eq!(already_exists, THREADS - 1);
499
500        let winner = results
501            .iter()
502            .find(|(result, _)| *result == FunctionRegistrationResult::Registered)
503            .map(|(_, factory)| factory)
504            .expect("exactly one registration must win");
505
506        let stored = registry
507            .get_function(name)
508            .expect("function should be registered");
509        assert!(
510            Arc::ptr_eq(&stored.factory, &winner.factory),
511            "the stored factory must be the factory of the winning registration"
512        );
513    }
514
515    #[test]
516    fn test_register_admin_function_first_wins() {
517        // Tests touching the global registry must use unique names.
518        let name = "pr3_admin_runtime_register";
519        let first = named_factory(name);
520        let second = named_factory(name);
521
522        assert_eq!(
523            register_admin_function(first.clone()),
524            FunctionRegistrationResult::Registered
525        );
526        assert_eq!(
527            register_admin_function(second.clone()),
528            FunctionRegistrationResult::AlreadyExists
529        );
530
531        let stored = get_admin_function(name).expect("admin function should be queryable");
532        assert!(Arc::ptr_eq(&stored.factory, &first.factory));
533        assert!(!Arc::ptr_eq(&stored.factory, &second.factory));
534    }
535
536    #[test]
537    fn test_register_admin_function_duplicate_same_factory() {
538        // The exact same factory clone registered twice: the first registration
539        // wins, the duplicate is rejected, and the stored factory is
540        // pointer-equal to the original. Tests touching the global registry
541        // must use unique names.
542        let name = "pr3_admin_runtime_register_same_factory";
543        let factory = named_factory(name);
544
545        assert_eq!(
546            register_admin_function(factory.clone()),
547            FunctionRegistrationResult::Registered
548        );
549        assert_eq!(
550            register_admin_function(factory.clone()),
551            FunctionRegistrationResult::AlreadyExists
552        );
553
554        let stored = get_admin_function(name).expect("admin function should be queryable");
555        assert!(Arc::ptr_eq(&stored.factory, &factory.factory));
556    }
557
558    #[test]
559    fn test_register_admin_function_in_is_one_way_later_normal_register_allowed() {
560        // The guard is one-way: after the ADMIN registration completes, an
561        // ordinary normal-registry registration of the same name still
562        // succeeds because the normal registry keeps its legacy replace
563        // semantics.
564        let admin = FunctionRegistry::default();
565        let normal = FunctionRegistry::default();
566        let name = "pr3_admin_in_one_way";
567        let admin_factory = named_factory(name);
568        let normal_factory = named_factory(name);
569
570        assert_eq!(
571            register_admin_function_in(&admin, &normal, admin_factory.clone()),
572            FunctionRegistrationResult::Registered
573        );
574
575        normal.register(normal_factory.clone());
576
577        let stored_admin = admin
578            .get_function(name)
579            .expect("the ADMIN registration must be kept");
580        assert!(Arc::ptr_eq(&stored_admin.factory, &admin_factory.factory));
581        let stored_normal = normal
582            .get_function(name)
583            .expect("the later normal registration must succeed");
584        assert!(Arc::ptr_eq(&stored_normal.factory, &normal_factory.factory));
585    }
586
587    #[test]
588    fn test_register_admin_function_rejects_normal_registry_builtin_name() {
589        // Regression test: the ADMIN executor resolves `get_admin_function`
590        // before falling back to `FUNCTION_REGISTRY`, so registering a function
591        // whose name already exists in the normal registry would shadow the
592        // ADMIN-invocable built-in (e.g. `flush_table`). Such registrations
593        // must be rejected with
594        // [`FunctionRegistrationResult::AlreadyExists`] and must not be
595        // inserted into the ADMIN registry.
596        let factory = named_factory("flush_table");
597
598        assert_eq!(
599            register_admin_function(factory.clone()),
600            FunctionRegistrationResult::AlreadyExists
601        );
602        assert!(
603            get_admin_function("flush_table").is_none(),
604            "a normal-registry built-in must not be shadowed into the ADMIN registry"
605        );
606        assert!(
607            FUNCTION_REGISTRY.get_function("flush_table").is_some(),
608            "the normal-registry built-in must remain registered"
609        );
610    }
611
612    #[test]
613    fn test_builtin_admin_functions_remain_queryable() {
614        // Built-in admin-only functions registered at startup stay queryable
615        // through the same global registry used for runtime registrations.
616        #[cfg(feature = "enterprise")]
617        {
618            assert!(get_admin_function("purge_table").is_some());
619        }
620        #[cfg(not(feature = "enterprise"))]
621        {
622            assert!(get_admin_function("purge_table").is_none());
623        }
624    }
625}