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