sql_cli/sql/functions/
mod.rs

1use anyhow::{anyhow, Result};
2use std::collections::HashMap;
3use std::fmt;
4use std::sync::Arc;
5
6use crate::data::datatable::DataValue;
7
8pub mod astronomy;
9pub mod case_convert;
10pub mod chemistry;
11pub mod comparison;
12pub mod constants;
13pub mod convert;
14pub mod date_time;
15pub mod financial;
16pub mod format;
17pub mod format_number;
18pub mod geometry;
19pub mod group_num;
20pub mod hash;
21pub mod math;
22pub mod mathematics;
23pub mod number_words;
24pub mod particle_charges;
25pub mod physics;
26pub mod random;
27pub mod roman;
28pub mod solar_system;
29pub mod statistics;
30pub mod string_fun;
31pub mod string_methods;
32pub mod string_utils;
33pub mod text_processing;
34pub mod type_checking;
35
36// Re-export MethodFunction trait
37pub use string_methods::MethodFunction;
38
39/// Category of SQL functions for organization and discovery
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
41pub enum FunctionCategory {
42    Constant,     // Mathematical and physical constants
43    Mathematical, // Mathematical operations
44    Statistical,  // Statistical functions
45    Astronomical, // Astronomical constants and calculations
46    Chemical,     // Chemical elements and properties
47    Date,         // Date/time operations
48    String,       // String manipulation
49    Aggregate,    // Aggregation functions
50    Conversion,   // Unit conversion functions
51}
52
53impl fmt::Display for FunctionCategory {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        match self {
56            FunctionCategory::Constant => write!(f, "Constant"),
57            FunctionCategory::Mathematical => write!(f, "Mathematical"),
58            FunctionCategory::Statistical => write!(f, "Statistical"),
59            FunctionCategory::Astronomical => write!(f, "Astronomical"),
60            FunctionCategory::Chemical => write!(f, "Chemical"),
61            FunctionCategory::Date => write!(f, "Date"),
62            FunctionCategory::String => write!(f, "String"),
63            FunctionCategory::Aggregate => write!(f, "Aggregate"),
64            FunctionCategory::Conversion => write!(f, "Conversion"),
65        }
66    }
67}
68
69/// Describes the number of arguments a function accepts
70#[derive(Debug, Clone)]
71pub enum ArgCount {
72    /// Exactly n arguments
73    Fixed(usize),
74    /// Between min and max arguments (inclusive)
75    Range(usize, usize),
76    /// Any number of arguments
77    Variadic,
78}
79
80impl ArgCount {
81    #[must_use]
82    pub fn is_valid(&self, count: usize) -> bool {
83        match self {
84            ArgCount::Fixed(n) => count == *n,
85            ArgCount::Range(min, max) => count >= *min && count <= *max,
86            ArgCount::Variadic => true,
87        }
88    }
89
90    #[must_use]
91    pub fn description(&self) -> String {
92        match self {
93            ArgCount::Fixed(0) => "no arguments".to_string(),
94            ArgCount::Fixed(1) => "1 argument".to_string(),
95            ArgCount::Fixed(n) => format!("{n} arguments"),
96            ArgCount::Range(min, max) => format!("{min} to {max} arguments"),
97            ArgCount::Variadic => "any number of arguments".to_string(),
98        }
99    }
100}
101
102/// Signature of a SQL function including metadata
103#[derive(Debug, Clone)]
104pub struct FunctionSignature {
105    pub name: &'static str,
106    pub category: FunctionCategory,
107    pub arg_count: ArgCount,
108    pub description: &'static str,
109    pub returns: &'static str,
110    pub examples: Vec<&'static str>,
111}
112
113/// Trait that all SQL functions must implement
114pub trait SqlFunction: Send + Sync {
115    /// Get the function's signature and metadata
116    fn signature(&self) -> FunctionSignature;
117
118    /// Evaluate the function with the given arguments
119    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue>;
120
121    /// Validate arguments before evaluation (default implementation checks count)
122    fn validate_args(&self, args: &[DataValue]) -> Result<()> {
123        let sig = self.signature();
124        if !sig.arg_count.is_valid(args.len()) {
125            return Err(anyhow!(
126                "{}() expects {}, got {}",
127                sig.name,
128                sig.arg_count.description(),
129                args.len()
130            ));
131        }
132        Ok(())
133    }
134}
135
136/// Registry for all SQL functions
137pub struct FunctionRegistry {
138    functions: HashMap<String, Box<dyn SqlFunction>>,
139    by_category: HashMap<FunctionCategory, Vec<String>>,
140    methods: HashMap<String, Arc<dyn MethodFunction>>,
141}
142
143impl FunctionRegistry {
144    /// Create a new registry with all built-in functions
145    #[must_use]
146    pub fn new() -> Self {
147        let mut registry = Self {
148            functions: HashMap::new(),
149            by_category: HashMap::new(),
150            methods: HashMap::new(),
151        };
152
153        // Register all built-in functions
154        registry.register_constants();
155        registry.register_astronomical_functions();
156        registry.register_chemical_functions();
157        registry.register_mathematical_functions();
158        registry.register_statistical_functions();
159        registry.register_geometry_functions();
160        registry.register_physics_functions();
161        registry.register_date_time_functions();
162        registry.register_string_methods();
163        registry.register_financial_functions();
164        registry.register_conversion_functions();
165        registry.register_hash_functions();
166        registry.register_comparison_functions();
167        registry.register_aggregate_functions();
168        registry.register_random_functions();
169        registry.register_format_functions();
170        registry.register_type_checking_functions();
171
172        registry
173    }
174
175    /// Register a function in the registry
176    pub fn register(&mut self, func: Box<dyn SqlFunction>) {
177        let sig = func.signature();
178        let name = sig.name.to_uppercase();
179        let category = sig.category;
180
181        // Add to main registry
182        self.functions.insert(name.clone(), func);
183
184        // Add to category index
185        self.by_category.entry(category).or_default().push(name);
186    }
187
188    /// Get a function by name (case-insensitive)
189    #[must_use]
190    pub fn get(&self, name: &str) -> Option<&dyn SqlFunction> {
191        self.functions
192            .get(&name.to_uppercase())
193            .map(std::convert::AsRef::as_ref)
194    }
195
196    /// Check if a function exists
197    #[must_use]
198    pub fn contains(&self, name: &str) -> bool {
199        self.functions.contains_key(&name.to_uppercase())
200    }
201
202    /// Get all functions matching a prefix (for autocomplete)
203    #[must_use]
204    pub fn autocomplete(&self, prefix: &str) -> Vec<FunctionSignature> {
205        let prefix_upper = prefix.to_uppercase();
206        self.functions
207            .iter()
208            .filter(|(name, _)| name.starts_with(&prefix_upper))
209            .map(|(_, func)| func.signature())
210            .collect()
211    }
212
213    /// Get all functions in a category
214    #[must_use]
215    pub fn get_by_category(&self, category: FunctionCategory) -> Vec<FunctionSignature> {
216        self.by_category
217            .get(&category)
218            .map(|names| {
219                names
220                    .iter()
221                    .filter_map(|name| self.functions.get(name))
222                    .map(|func| func.signature())
223                    .collect()
224            })
225            .unwrap_or_default()
226    }
227
228    /// Get all available functions
229    #[must_use]
230    pub fn all_functions(&self) -> Vec<FunctionSignature> {
231        self.functions
232            .values()
233            .map(|func| func.signature())
234            .collect()
235    }
236
237    /// Register a method function
238    pub fn register_method(&mut self, method: Arc<dyn MethodFunction>) {
239        let method_name = method.method_name().to_uppercase();
240        self.methods.insert(method_name, method);
241    }
242
243    /// Get a method function by name
244    #[must_use]
245    pub fn get_method(&self, name: &str) -> Option<Arc<dyn MethodFunction>> {
246        // Try exact match first
247        if let Some(method) = self.methods.get(&name.to_uppercase()) {
248            return Some(Arc::clone(method));
249        }
250
251        // Try to find a method that handles this name
252        for method in self.methods.values() {
253            if method.handles_method(name) {
254                return Some(Arc::clone(method));
255            }
256        }
257
258        None
259    }
260
261    /// Check if a method exists
262    #[must_use]
263    pub fn has_method(&self, name: &str) -> bool {
264        self.get_method(name).is_some()
265    }
266
267    /// Generate markdown documentation for all functions
268    #[must_use]
269    pub fn generate_markdown_docs(&self) -> String {
270        use std::fmt::Write;
271        let mut doc = String::new();
272
273        writeln!(&mut doc, "# SQL CLI Function Reference\n").unwrap();
274        writeln!(
275            &mut doc,
276            "This document is auto-generated from the function registry.\n"
277        )
278        .unwrap();
279
280        // Get all categories in a deterministic order
281        let mut categories: Vec<FunctionCategory> = self.by_category.keys().copied().collect();
282        categories.sort_by_key(|c| format!("{c:?}"));
283
284        for category in categories {
285            let functions = self.get_by_category(category);
286            if functions.is_empty() {
287                continue;
288            }
289
290            writeln!(&mut doc, "## {category} Functions\n").unwrap();
291
292            // Sort functions by name for consistent output
293            let mut functions = functions;
294            functions.sort_by_key(|f| f.name);
295
296            for func in functions {
297                writeln!(&mut doc, "### {}()\n", func.name).unwrap();
298                writeln!(&mut doc, "**Description:** {}\n", func.description).unwrap();
299                writeln!(
300                    &mut doc,
301                    "**Arguments:** {}\n",
302                    func.arg_count.description()
303                )
304                .unwrap();
305                writeln!(&mut doc, "**Returns:** {}\n", func.returns).unwrap();
306
307                if !func.examples.is_empty() {
308                    writeln!(&mut doc, "**Examples:**").unwrap();
309                    writeln!(&mut doc, "```sql").unwrap();
310                    for example in &func.examples {
311                        writeln!(&mut doc, "{example}").unwrap();
312                    }
313                    writeln!(&mut doc, "```\n").unwrap();
314                }
315            }
316        }
317
318        doc
319    }
320
321    /// Generate help text for a specific function
322    #[must_use]
323    pub fn generate_function_help(&self, name: &str) -> Option<String> {
324        self.get(name).map(|func| {
325            let sig = func.signature();
326            let mut help = String::new();
327            use std::fmt::Write;
328
329            writeln!(&mut help, "Function: {}()", sig.name).unwrap();
330            writeln!(&mut help, "Category: {}", sig.category).unwrap();
331            writeln!(&mut help, "Description: {}", sig.description).unwrap();
332            writeln!(&mut help, "Arguments: {}", sig.arg_count.description()).unwrap();
333            writeln!(&mut help, "Returns: {}", sig.returns).unwrap();
334
335            if !sig.examples.is_empty() {
336                writeln!(&mut help, "\nExamples:").unwrap();
337                for example in &sig.examples {
338                    writeln!(&mut help, "  {example}").unwrap();
339                }
340            }
341
342            help
343        })
344    }
345
346    /// List all available functions with brief descriptions
347    #[must_use]
348    pub fn list_functions(&self) -> String {
349        use std::fmt::Write;
350        let mut list = String::new();
351
352        writeln!(&mut list, "Available SQL Functions:\n").unwrap();
353
354        let mut categories: Vec<FunctionCategory> = self.by_category.keys().copied().collect();
355        categories.sort_by_key(|c| format!("{c:?}"));
356
357        for category in categories {
358            let functions = self.get_by_category(category);
359            if functions.is_empty() {
360                continue;
361            }
362
363            writeln!(&mut list, "{category} Functions:").unwrap();
364
365            let mut functions = functions;
366            functions.sort_by_key(|f| f.name);
367
368            for func in functions {
369                writeln!(
370                    &mut list,
371                    "  {:20} - {}",
372                    format!("{}()", func.name),
373                    func.description
374                )
375                .unwrap();
376            }
377            writeln!(&mut list).unwrap();
378        }
379
380        list
381    }
382
383    /// Register constant functions
384    fn register_constants(&mut self) {
385        use constants::{
386            EFunction, HbarFunction, MassElectronFunction, MeFunction, PhiFunction, PiFunction,
387            TauFunction,
388        };
389
390        self.register(Box::new(PiFunction));
391        self.register(Box::new(EFunction));
392        self.register(Box::new(MeFunction)); // Mass of electron
393        self.register(Box::new(MassElectronFunction)); // Alias for ME
394        self.register(Box::new(TauFunction));
395        self.register(Box::new(PhiFunction));
396        self.register(Box::new(HbarFunction));
397    }
398
399    /// Register astronomical functions
400    fn register_astronomical_functions(&mut self) {
401        use astronomy::{
402            AuFunction, DistJupiterFunction, DistMarsFunction, DistMercuryFunction,
403            DistNeptuneFunction, DistSaturnFunction, DistUranusFunction, DistVenusFunction,
404            LightYearFunction, MassEarthFunction, MassJupiterFunction, MassMarsFunction,
405            MassMercuryFunction, MassMoonFunction, MassNeptuneFunction, MassSaturnFunction,
406            MassSunFunction, MassUranusFunction, MassVenusFunction, ParsecFunction,
407            RadiusEarthFunction, RadiusJupiterFunction, RadiusMarsFunction, RadiusMercuryFunction,
408            RadiusMoonFunction, RadiusNeptuneFunction, RadiusSaturnFunction, RadiusSunFunction,
409            RadiusUranusFunction, RadiusVenusFunction,
410        };
411
412        use solar_system::{
413            DensitySolarBodyFunction, DistanceSolarBodyFunction, EscapeVelocitySolarBodyFunction,
414            GravitySolarBodyFunction, MassSolarBodyFunction, MoonsSolarBodyFunction,
415            OrbitalPeriodSolarBodyFunction, RadiusSolarBodyFunction,
416            RotationPeriodSolarBodyFunction,
417        };
418
419        self.register(Box::new(MassEarthFunction));
420        self.register(Box::new(MassSunFunction));
421        self.register(Box::new(MassMoonFunction));
422        self.register(Box::new(AuFunction)); // Astronomical unit
423        self.register(Box::new(LightYearFunction));
424        self.register(Box::new(ParsecFunction));
425
426        // Planetary masses
427        self.register(Box::new(MassMercuryFunction));
428        self.register(Box::new(MassVenusFunction));
429        self.register(Box::new(MassMarsFunction));
430        self.register(Box::new(MassJupiterFunction));
431        self.register(Box::new(MassSaturnFunction));
432        self.register(Box::new(MassUranusFunction));
433        self.register(Box::new(MassNeptuneFunction));
434
435        // Solar body radius functions
436        self.register(Box::new(RadiusSunFunction));
437        self.register(Box::new(RadiusEarthFunction));
438        self.register(Box::new(RadiusMoonFunction));
439        self.register(Box::new(RadiusMercuryFunction));
440        self.register(Box::new(RadiusVenusFunction));
441        self.register(Box::new(RadiusMarsFunction));
442        self.register(Box::new(RadiusJupiterFunction));
443        self.register(Box::new(RadiusSaturnFunction));
444        self.register(Box::new(RadiusUranusFunction));
445        self.register(Box::new(RadiusNeptuneFunction));
446
447        // Planetary distances from the Sun
448        self.register(Box::new(DistMercuryFunction));
449        self.register(Box::new(DistVenusFunction));
450        self.register(Box::new(DistMarsFunction));
451        self.register(Box::new(DistJupiterFunction));
452        self.register(Box::new(DistSaturnFunction));
453        self.register(Box::new(DistUranusFunction));
454        self.register(Box::new(DistNeptuneFunction));
455
456        // Solar system lookup functions
457        self.register(Box::new(MassSolarBodyFunction));
458        self.register(Box::new(RadiusSolarBodyFunction));
459        self.register(Box::new(DistanceSolarBodyFunction));
460        self.register(Box::new(OrbitalPeriodSolarBodyFunction));
461        self.register(Box::new(GravitySolarBodyFunction));
462        self.register(Box::new(DensitySolarBodyFunction));
463        self.register(Box::new(EscapeVelocitySolarBodyFunction));
464        self.register(Box::new(RotationPeriodSolarBodyFunction));
465        self.register(Box::new(MoonsSolarBodyFunction));
466    }
467
468    /// Register chemical functions
469    fn register_chemical_functions(&mut self) {
470        use chemistry::{
471            AtomicMassFunction, AtomicNumberFunction, AvogadroFunction, MoleculeFormulaFunction,
472            NeutronsFunction,
473        };
474
475        self.register(Box::new(AvogadroFunction));
476        self.register(Box::new(AtomicMassFunction));
477        self.register(Box::new(AtomicNumberFunction));
478        self.register(Box::new(NeutronsFunction));
479        self.register(Box::new(MoleculeFormulaFunction));
480    }
481
482    /// Register string method functions
483    fn register_string_methods(&mut self) {
484        use case_convert::{
485            ToCamelCaseFunction, ToConstantCaseFunction, ToKebabCaseFunction, ToPascalCaseFunction,
486            ToSnakeCaseFunction,
487        };
488        use number_words::{ToOrdinal, ToOrdinalWords, ToWords};
489        use string_fun::{
490            InitCapFunction, MorseCodeFunction, PigLatinFunction, ProperFunction, ReverseFunction,
491            Rot13Function, ScrambleFunction, SoundexFunction,
492        };
493        use string_utils::{LPadFunction, RPadFunction, RepeatFunction};
494        use text_processing::{CleanText, ExtractWords, StripPunctuation, Tokenize, WordCount};
495
496        string_methods::register_string_methods(self);
497
498        // String utility functions
499        self.register(Box::new(RepeatFunction));
500        self.register(Box::new(LPadFunction));
501        self.register(Box::new(RPadFunction));
502
503        // Case conversion functions
504        self.register(Box::new(ToSnakeCaseFunction));
505        self.register(Box::new(ToCamelCaseFunction));
506        self.register(Box::new(ToPascalCaseFunction));
507        self.register(Box::new(ToKebabCaseFunction));
508        self.register(Box::new(ToConstantCaseFunction));
509
510        // String fun & transformation functions
511        self.register(Box::new(ReverseFunction));
512        self.register(Box::new(InitCapFunction));
513        self.register(Box::new(ProperFunction));
514        self.register(Box::new(Rot13Function));
515        self.register(Box::new(SoundexFunction));
516        self.register(Box::new(PigLatinFunction));
517        self.register(Box::new(MorseCodeFunction));
518        self.register(Box::new(ScrambleFunction));
519
520        // Number to words functions
521        self.register(Box::new(ToWords));
522        self.register(Box::new(ToOrdinal));
523        self.register(Box::new(ToOrdinalWords));
524
525        // Text processing functions
526        self.register(Box::new(StripPunctuation));
527        self.register(Box::new(Tokenize));
528        self.register(Box::new(CleanText));
529        self.register(Box::new(ExtractWords));
530        self.register(Box::new(WordCount));
531    }
532
533    /// Register geometry functions
534    fn register_geometry_functions(&mut self) {
535        use geometry::{
536            CircleAreaFunction, CircleCircumferenceFunction, Distance2DFunction,
537            PythagorasFunction, SphereSurfaceAreaFunction, SphereVolumeFunction,
538            TriangleAreaFunction,
539        };
540
541        self.register(Box::new(PythagorasFunction));
542        self.register(Box::new(CircleAreaFunction));
543        self.register(Box::new(CircleCircumferenceFunction));
544        self.register(Box::new(SphereVolumeFunction));
545        self.register(Box::new(SphereSurfaceAreaFunction));
546        self.register(Box::new(TriangleAreaFunction));
547        self.register(Box::new(Distance2DFunction));
548    }
549
550    /// Register hash functions
551    fn register_hash_functions(&mut self) {
552        use hash::{Md5Function, Sha1Function, Sha256Function, Sha512Function};
553
554        self.register(Box::new(Md5Function));
555        self.register(Box::new(Sha1Function));
556        self.register(Box::new(Sha256Function));
557        self.register(Box::new(Sha512Function));
558    }
559
560    /// Register comparison functions
561    fn register_comparison_functions(&mut self) {
562        comparison::register_comparison_functions(self);
563    }
564
565    /// Register mathematical functions
566    fn register_mathematical_functions(&mut self) {
567        use mathematics::{
568            IsPrimeFunction, NextPrimeFunction, NthPrimeFunction, PrevPrimeFunction,
569            PrimeCountFunction, PrimeFunction, PrimePiFunction,
570        };
571
572        // Prime number functions
573        self.register(Box::new(PrimeFunction));
574        self.register(Box::new(NthPrimeFunction)); // Alias for PRIME
575        self.register(Box::new(IsPrimeFunction));
576        self.register(Box::new(PrimeCountFunction));
577        self.register(Box::new(PrimePiFunction)); // Alias for PRIME_COUNT
578        self.register(Box::new(NextPrimeFunction));
579        self.register(Box::new(PrevPrimeFunction));
580
581        // General math functions
582        math::register_math_functions(self);
583    }
584
585    /// Register physics constants
586    fn register_physics_functions(&mut self) {
587        physics::register_physics_functions(self);
588
589        // Register particle charge functions
590        use particle_charges::{
591            ChargeDownQuarkFunction, ChargeElectronFunction, ChargeMuonFunction,
592            ChargeNeutronFunction, ChargePositronFunction, ChargeProtonFunction, ChargeTauFunction,
593            ChargeUpQuarkFunction,
594        };
595
596        self.register(Box::new(ChargeElectronFunction));
597        self.register(Box::new(ChargeProtonFunction));
598        self.register(Box::new(ChargeNeutronFunction));
599        self.register(Box::new(ChargeUpQuarkFunction));
600        self.register(Box::new(ChargeDownQuarkFunction));
601        self.register(Box::new(ChargePositronFunction));
602        self.register(Box::new(ChargeMuonFunction));
603        self.register(Box::new(ChargeTauFunction));
604    }
605
606    /// Register date/time functions
607    fn register_date_time_functions(&mut self) {
608        date_time::register_date_time_functions(self);
609    }
610
611    /// Register financial functions
612    fn register_financial_functions(&mut self) {
613        financial::register_financial_functions(self);
614    }
615
616    /// Register conversion functions
617    fn register_conversion_functions(&mut self) {
618        use convert::ConvertFunction;
619        use roman::{FromRoman, ToRoman};
620
621        self.register(Box::new(ConvertFunction));
622        self.register(Box::new(ToRoman));
623        self.register(Box::new(FromRoman));
624    }
625
626    /// Register statistical functions
627    fn register_statistical_functions(&mut self) {
628        use statistics::{
629            CorrelationFunction, KurtosisFunction, MedianFunction, ModeFunction,
630            PercentileFunction, SkewFunction, VarPopFunction, VarSampFunction, VarianceFunction,
631        };
632
633        self.register(Box::new(MedianFunction));
634        self.register(Box::new(PercentileFunction));
635        self.register(Box::new(ModeFunction));
636        self.register(Box::new(VarianceFunction));
637        self.register(Box::new(VarSampFunction));
638        self.register(Box::new(VarPopFunction));
639        self.register(Box::new(CorrelationFunction));
640        self.register(Box::new(SkewFunction));
641        self.register(Box::new(KurtosisFunction));
642    }
643
644    /// Register aggregate and analytic functions
645    fn register_aggregate_functions(&mut self) {
646        use group_num::GroupNumFunction;
647
648        // Register GROUP_NUM function
649        // Note: We create a new instance per query to ensure clean memoization
650        self.register(Box::new(GroupNumFunction::new()));
651    }
652
653    /// Register random number generation functions
654    fn register_random_functions(&mut self) {
655        use random::{RandIntFunction, RandRangeFunction, RandomFunction};
656
657        self.register(Box::new(RandomFunction));
658        self.register(Box::new(RandIntFunction));
659        self.register(Box::new(RandRangeFunction));
660    }
661
662    /// Register formatting functions
663    fn register_format_functions(&mut self) {
664        use format::{
665            CenterFunction, FormatDateFunction, FormatNumberFunction, LPadFunction, RPadFunction,
666        };
667        use format_number::{FormatCurrencyFunction, RenderNumberFunction};
668
669        self.register(Box::new(FormatNumberFunction));
670        self.register(Box::new(FormatDateFunction));
671        self.register(Box::new(LPadFunction));
672        self.register(Box::new(RPadFunction));
673        self.register(Box::new(CenterFunction));
674        self.register(Box::new(RenderNumberFunction));
675        self.register(Box::new(FormatCurrencyFunction));
676    }
677
678    /// Register type checking functions
679    fn register_type_checking_functions(&mut self) {
680        use type_checking::{
681            IsBoolFunction, IsDateFunction, IsFloatFunction, IsIntegerFunction, IsNotNullFunction,
682            IsNullFunction, IsNumericFunction,
683        };
684
685        self.register(Box::new(IsDateFunction));
686        self.register(Box::new(IsBoolFunction));
687        self.register(Box::new(IsNumericFunction));
688        self.register(Box::new(IsIntegerFunction));
689        self.register(Box::new(IsFloatFunction));
690        self.register(Box::new(IsNullFunction));
691        self.register(Box::new(IsNotNullFunction));
692    }
693}
694
695impl Default for FunctionRegistry {
696    fn default() -> Self {
697        Self::new()
698    }
699}
700
701#[cfg(test)]
702mod tests {
703    use super::*;
704
705    #[test]
706    fn test_registry_creation() {
707        let registry = FunctionRegistry::new();
708
709        // Check that some known functions exist
710        assert!(registry.contains("PI"));
711        assert!(registry.contains("MASS_EARTH"));
712        assert!(registry.contains("ME"));
713    }
714
715    #[test]
716    fn test_case_insensitive_lookup() {
717        let registry = FunctionRegistry::new();
718
719        assert!(registry.get("pi").is_some());
720        assert!(registry.get("PI").is_some());
721        assert!(registry.get("Pi").is_some());
722    }
723
724    #[test]
725    fn test_autocomplete() {
726        let registry = FunctionRegistry::new();
727
728        let mass_functions = registry.autocomplete("MASS");
729        assert!(!mass_functions.is_empty());
730
731        // Should include MASS_EARTH, MASS_SUN, etc.
732        let names: Vec<&str> = mass_functions.iter().map(|sig| sig.name).collect();
733        assert!(names.contains(&"MASS_EARTH"));
734        assert!(names.contains(&"MASS_SUN"));
735    }
736}