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