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;
39pub mod utility;
40
41pub use string_methods::MethodFunction;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46pub enum FunctionCategory {
47 Constant, Mathematical, Statistical, Astronomical, Chemical, Date, String, Aggregate, Conversion, BigNumber, TableFunction, }
59
60impl fmt::Display for FunctionCategory {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 FunctionCategory::Constant => write!(f, "Constant"),
64 FunctionCategory::Mathematical => write!(f, "Mathematical"),
65 FunctionCategory::Statistical => write!(f, "Statistical"),
66 FunctionCategory::Astronomical => write!(f, "Astronomical"),
67 FunctionCategory::Chemical => write!(f, "Chemical"),
68 FunctionCategory::Date => write!(f, "Date"),
69 FunctionCategory::String => write!(f, "String"),
70 FunctionCategory::Aggregate => write!(f, "Aggregate"),
71 FunctionCategory::Conversion => write!(f, "Conversion"),
72 FunctionCategory::BigNumber => write!(f, "BigNumber"),
73 FunctionCategory::TableFunction => write!(f, "TableFunction"),
74 }
75 }
76}
77
78#[derive(Debug, Clone)]
80pub enum ArgCount {
81 Fixed(usize),
83 Range(usize, usize),
85 Variadic,
87}
88
89impl ArgCount {
90 #[must_use]
91 pub fn is_valid(&self, count: usize) -> bool {
92 match self {
93 ArgCount::Fixed(n) => count == *n,
94 ArgCount::Range(min, max) => count >= *min && count <= *max,
95 ArgCount::Variadic => true,
96 }
97 }
98
99 #[must_use]
100 pub fn description(&self) -> String {
101 match self {
102 ArgCount::Fixed(0) => "no arguments".to_string(),
103 ArgCount::Fixed(1) => "1 argument".to_string(),
104 ArgCount::Fixed(n) => format!("{n} arguments"),
105 ArgCount::Range(min, max) => format!("{min} to {max} arguments"),
106 ArgCount::Variadic => "any number of arguments".to_string(),
107 }
108 }
109}
110
111#[derive(Debug, Clone)]
113pub struct FunctionSignature {
114 pub name: &'static str,
115 pub category: FunctionCategory,
116 pub arg_count: ArgCount,
117 pub description: &'static str,
118 pub returns: &'static str,
119 pub examples: Vec<&'static str>,
120}
121
122pub trait SqlFunction: Send + Sync {
124 fn signature(&self) -> FunctionSignature;
126
127 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue>;
129
130 fn validate_args(&self, args: &[DataValue]) -> Result<()> {
132 let sig = self.signature();
133 if !sig.arg_count.is_valid(args.len()) {
134 return Err(anyhow!(
135 "{}() expects {}, got {}",
136 sig.name,
137 sig.arg_count.description(),
138 args.len()
139 ));
140 }
141 Ok(())
142 }
143}
144
145pub struct FunctionRegistry {
147 functions: HashMap<String, Box<dyn SqlFunction>>,
148 by_category: HashMap<FunctionCategory, Vec<String>>,
149 methods: HashMap<String, Arc<dyn MethodFunction>>,
150}
151
152impl FunctionRegistry {
153 #[must_use]
155 pub fn new() -> Self {
156 let mut registry = Self {
157 functions: HashMap::new(),
158 by_category: HashMap::new(),
159 methods: HashMap::new(),
160 };
161
162 registry.register_constants();
164 registry.register_astronomical_functions();
165 registry.register_chemical_functions();
166 registry.register_mathematical_functions();
167 registry.register_statistical_functions();
168 registry.register_geometry_functions();
169 registry.register_physics_functions();
170 registry.register_date_time_functions();
171 registry.register_string_methods();
172 registry.register_financial_functions();
173 registry.register_bigint_functions();
174 registry.register_conversion_functions();
175 registry.register_hash_functions();
176 registry.register_comparison_functions();
177 registry.register_aggregate_functions();
178 registry.register_random_functions();
179 registry.register_format_functions();
180 registry.register_type_checking_functions();
181 registry.register_utility_functions();
182
183 registry
184 }
185
186 pub fn register(&mut self, func: Box<dyn SqlFunction>) {
188 let sig = func.signature();
189 let name = sig.name.to_uppercase();
190 let category = sig.category;
191
192 self.functions.insert(name.clone(), func);
194
195 self.by_category.entry(category).or_default().push(name);
197 }
198
199 #[must_use]
201 pub fn get(&self, name: &str) -> Option<&dyn SqlFunction> {
202 self.functions
203 .get(&name.to_uppercase())
204 .map(std::convert::AsRef::as_ref)
205 }
206
207 #[must_use]
209 pub fn contains(&self, name: &str) -> bool {
210 self.functions.contains_key(&name.to_uppercase())
211 }
212
213 #[must_use]
215 pub fn autocomplete(&self, prefix: &str) -> Vec<FunctionSignature> {
216 let prefix_upper = prefix.to_uppercase();
217 self.functions
218 .iter()
219 .filter(|(name, _)| name.starts_with(&prefix_upper))
220 .map(|(_, func)| func.signature())
221 .collect()
222 }
223
224 #[must_use]
226 pub fn get_by_category(&self, category: FunctionCategory) -> Vec<FunctionSignature> {
227 self.by_category
228 .get(&category)
229 .map(|names| {
230 names
231 .iter()
232 .filter_map(|name| self.functions.get(name))
233 .map(|func| func.signature())
234 .collect()
235 })
236 .unwrap_or_default()
237 }
238
239 #[must_use]
241 pub fn all_functions(&self) -> Vec<FunctionSignature> {
242 self.functions
243 .values()
244 .map(|func| func.signature())
245 .collect()
246 }
247
248 pub fn register_method(&mut self, method: Arc<dyn MethodFunction>) {
250 let method_name = method.method_name().to_uppercase();
251 self.methods.insert(method_name, method);
252 }
253
254 #[must_use]
256 pub fn get_method(&self, name: &str) -> Option<Arc<dyn MethodFunction>> {
257 if let Some(method) = self.methods.get(&name.to_uppercase()) {
259 return Some(Arc::clone(method));
260 }
261
262 for method in self.methods.values() {
264 if method.handles_method(name) {
265 return Some(Arc::clone(method));
266 }
267 }
268
269 None
270 }
271
272 #[must_use]
274 pub fn has_method(&self, name: &str) -> bool {
275 self.get_method(name).is_some()
276 }
277
278 #[must_use]
280 pub fn generate_markdown_docs(&self) -> String {
281 use std::fmt::Write;
282 let mut doc = String::new();
283
284 writeln!(&mut doc, "# SQL CLI Function Reference\n").unwrap();
285 writeln!(
286 &mut doc,
287 "This document is auto-generated from the function registry.\n"
288 )
289 .unwrap();
290
291 let mut categories: Vec<FunctionCategory> = self.by_category.keys().copied().collect();
293 categories.sort_by_key(|c| format!("{c:?}"));
294
295 for category in categories {
296 let functions = self.get_by_category(category);
297 if functions.is_empty() {
298 continue;
299 }
300
301 writeln!(&mut doc, "## {category} Functions\n").unwrap();
302
303 let mut functions = functions;
305 functions.sort_by_key(|f| f.name);
306
307 for func in functions {
308 writeln!(&mut doc, "### {}()\n", func.name).unwrap();
309 writeln!(&mut doc, "**Description:** {}\n", func.description).unwrap();
310 writeln!(
311 &mut doc,
312 "**Arguments:** {}\n",
313 func.arg_count.description()
314 )
315 .unwrap();
316 writeln!(&mut doc, "**Returns:** {}\n", func.returns).unwrap();
317
318 if !func.examples.is_empty() {
319 writeln!(&mut doc, "**Examples:**").unwrap();
320 writeln!(&mut doc, "```sql").unwrap();
321 for example in &func.examples {
322 writeln!(&mut doc, "{example}").unwrap();
323 }
324 writeln!(&mut doc, "```\n").unwrap();
325 }
326 }
327 }
328
329 doc
330 }
331
332 #[must_use]
334 pub fn generate_function_help(&self, name: &str) -> Option<String> {
335 self.get(name).map(|func| {
336 let sig = func.signature();
337 let mut help = String::new();
338 use std::fmt::Write;
339
340 writeln!(&mut help, "Function: {}()", sig.name).unwrap();
341 writeln!(&mut help, "Category: {}", sig.category).unwrap();
342 writeln!(&mut help, "Description: {}", sig.description).unwrap();
343 writeln!(&mut help, "Arguments: {}", sig.arg_count.description()).unwrap();
344 writeln!(&mut help, "Returns: {}", sig.returns).unwrap();
345
346 if !sig.examples.is_empty() {
347 writeln!(&mut help, "\nExamples:").unwrap();
348 for example in &sig.examples {
349 writeln!(&mut help, " {example}").unwrap();
350 }
351 }
352
353 help
354 })
355 }
356
357 #[must_use]
359 pub fn list_functions(&self) -> String {
360 use std::fmt::Write;
361 let mut list = String::new();
362
363 writeln!(&mut list, "Available SQL Functions:\n").unwrap();
364
365 let mut categories: Vec<FunctionCategory> = self.by_category.keys().copied().collect();
366 categories.sort_by_key(|c| format!("{c:?}"));
367
368 for category in categories {
369 let functions = self.get_by_category(category);
370 if functions.is_empty() {
371 continue;
372 }
373
374 writeln!(&mut list, "{category} Functions:").unwrap();
375
376 let mut functions = functions;
377 functions.sort_by_key(|f| f.name);
378
379 for func in functions {
380 writeln!(
381 &mut list,
382 " {:20} - {}",
383 format!("{}()", func.name),
384 func.description
385 )
386 .unwrap();
387 }
388 writeln!(&mut list).unwrap();
389 }
390
391 list
392 }
393
394 fn register_constants(&mut self) {
396 use constants::{
397 EFunction, HbarFunction, MassElectronFunction, MeFunction, PhiFunction, PiFunction,
398 TauFunction,
399 };
400
401 self.register(Box::new(PiFunction));
402 self.register(Box::new(EFunction));
403 self.register(Box::new(MeFunction)); self.register(Box::new(MassElectronFunction)); self.register(Box::new(TauFunction));
406 self.register(Box::new(PhiFunction));
407 self.register(Box::new(HbarFunction));
408 }
409
410 fn register_astronomical_functions(&mut self) {
412 use astronomy::{
413 AuFunction, DistJupiterFunction, DistMarsFunction, DistMercuryFunction,
414 DistNeptuneFunction, DistSaturnFunction, DistUranusFunction, DistVenusFunction,
415 LightYearFunction, MassEarthFunction, MassJupiterFunction, MassMarsFunction,
416 MassMercuryFunction, MassMoonFunction, MassNeptuneFunction, MassSaturnFunction,
417 MassSunFunction, MassUranusFunction, MassVenusFunction, ParsecFunction,
418 RadiusEarthFunction, RadiusJupiterFunction, RadiusMarsFunction, RadiusMercuryFunction,
419 RadiusMoonFunction, RadiusNeptuneFunction, RadiusSaturnFunction, RadiusSunFunction,
420 RadiusUranusFunction, RadiusVenusFunction,
421 };
422
423 use solar_system::{
424 DensitySolarBodyFunction, DistanceSolarBodyFunction, EscapeVelocitySolarBodyFunction,
425 GravitySolarBodyFunction, MassSolarBodyFunction, MoonsSolarBodyFunction,
426 OrbitalPeriodSolarBodyFunction, RadiusSolarBodyFunction,
427 RotationPeriodSolarBodyFunction,
428 };
429
430 self.register(Box::new(MassEarthFunction));
431 self.register(Box::new(MassSunFunction));
432 self.register(Box::new(MassMoonFunction));
433 self.register(Box::new(AuFunction)); self.register(Box::new(LightYearFunction));
435 self.register(Box::new(ParsecFunction));
436
437 self.register(Box::new(MassMercuryFunction));
439 self.register(Box::new(MassVenusFunction));
440 self.register(Box::new(MassMarsFunction));
441 self.register(Box::new(MassJupiterFunction));
442 self.register(Box::new(MassSaturnFunction));
443 self.register(Box::new(MassUranusFunction));
444 self.register(Box::new(MassNeptuneFunction));
445
446 self.register(Box::new(RadiusSunFunction));
448 self.register(Box::new(RadiusEarthFunction));
449 self.register(Box::new(RadiusMoonFunction));
450 self.register(Box::new(RadiusMercuryFunction));
451 self.register(Box::new(RadiusVenusFunction));
452 self.register(Box::new(RadiusMarsFunction));
453 self.register(Box::new(RadiusJupiterFunction));
454 self.register(Box::new(RadiusSaturnFunction));
455 self.register(Box::new(RadiusUranusFunction));
456 self.register(Box::new(RadiusNeptuneFunction));
457
458 self.register(Box::new(DistMercuryFunction));
460 self.register(Box::new(DistVenusFunction));
461 self.register(Box::new(DistMarsFunction));
462 self.register(Box::new(DistJupiterFunction));
463 self.register(Box::new(DistSaturnFunction));
464 self.register(Box::new(DistUranusFunction));
465 self.register(Box::new(DistNeptuneFunction));
466
467 self.register(Box::new(MassSolarBodyFunction));
469 self.register(Box::new(RadiusSolarBodyFunction));
470 self.register(Box::new(DistanceSolarBodyFunction));
471 self.register(Box::new(OrbitalPeriodSolarBodyFunction));
472 self.register(Box::new(GravitySolarBodyFunction));
473 self.register(Box::new(DensitySolarBodyFunction));
474 self.register(Box::new(EscapeVelocitySolarBodyFunction));
475 self.register(Box::new(RotationPeriodSolarBodyFunction));
476 self.register(Box::new(MoonsSolarBodyFunction));
477 }
478
479 fn register_chemical_functions(&mut self) {
481 use chemistry::{
482 AtomicMassFunction, AtomicNumberFunction, AvogadroFunction, MoleculeFormulaFunction,
483 NeutronsFunction,
484 };
485
486 self.register(Box::new(AvogadroFunction));
487 self.register(Box::new(AtomicMassFunction));
488 self.register(Box::new(AtomicNumberFunction));
489 self.register(Box::new(NeutronsFunction));
490 self.register(Box::new(MoleculeFormulaFunction));
491 }
492
493 fn register_string_methods(&mut self) {
495 use case_convert::{
496 ToCamelCaseFunction, ToConstantCaseFunction, ToKebabCaseFunction, ToPascalCaseFunction,
497 ToSnakeCaseFunction,
498 };
499 use number_words::{ToOrdinal, ToOrdinalWords, ToWords};
500 use string_fun::{
501 InitCapFunction, MorseCodeFunction, PigLatinFunction, ProperFunction, ReverseFunction,
502 Rot13Function, ScrambleFunction, SoundexFunction,
503 };
504 use string_utils::{LPadFunction, RPadFunction, RepeatFunction};
505 use text_processing::{CleanText, ExtractWords, StripPunctuation, Tokenize, WordCount};
506
507 string_methods::register_string_methods(self);
508
509 self.register(Box::new(RepeatFunction));
511 self.register(Box::new(LPadFunction));
512 self.register(Box::new(RPadFunction));
513
514 self.register(Box::new(ToSnakeCaseFunction));
516 self.register(Box::new(ToCamelCaseFunction));
517 self.register(Box::new(ToPascalCaseFunction));
518 self.register(Box::new(ToKebabCaseFunction));
519 self.register(Box::new(ToConstantCaseFunction));
520
521 self.register(Box::new(ReverseFunction));
523 self.register(Box::new(InitCapFunction));
524 self.register(Box::new(ProperFunction));
525 self.register(Box::new(Rot13Function));
526 self.register(Box::new(SoundexFunction));
527 self.register(Box::new(PigLatinFunction));
528 self.register(Box::new(MorseCodeFunction));
529 self.register(Box::new(ScrambleFunction));
530
531 self.register(Box::new(ToWords));
533 self.register(Box::new(ToOrdinal));
534 self.register(Box::new(ToOrdinalWords));
535
536 self.register(Box::new(StripPunctuation));
538 self.register(Box::new(Tokenize));
539 self.register(Box::new(CleanText));
540 self.register(Box::new(ExtractWords));
541 self.register(Box::new(WordCount));
542 }
543
544 fn register_geometry_functions(&mut self) {
546 use geometry::{
547 CircleAreaFunction, CircleCircumferenceFunction, Distance2DFunction,
548 PythagorasFunction, SphereSurfaceAreaFunction, SphereVolumeFunction,
549 TriangleAreaFunction,
550 };
551
552 self.register(Box::new(PythagorasFunction));
553 self.register(Box::new(CircleAreaFunction));
554 self.register(Box::new(CircleCircumferenceFunction));
555 self.register(Box::new(SphereVolumeFunction));
556 self.register(Box::new(SphereSurfaceAreaFunction));
557 self.register(Box::new(TriangleAreaFunction));
558 self.register(Box::new(Distance2DFunction));
559 }
560
561 fn register_hash_functions(&mut self) {
563 use hash::{Md5Function, Sha1Function, Sha256Function, Sha512Function};
564
565 self.register(Box::new(Md5Function));
566 self.register(Box::new(Sha1Function));
567 self.register(Box::new(Sha256Function));
568 self.register(Box::new(Sha512Function));
569 }
570
571 fn register_comparison_functions(&mut self) {
573 comparison::register_comparison_functions(self);
574 }
575
576 fn register_mathematical_functions(&mut self) {
578 use base_conversion::{
579 FromBase, FromBinary, FromHex, FromOctal, ToBase, ToBinary, ToHex, ToOctal,
580 };
581 use integer_limits::{
582 ByteMax, ByteMin, CharMax, CharMin, Int16Max, Int16Min, Int32Max, Int32Min, Int64Max,
583 Int64Min, Int8Max, Int8Min, IntMax, IntMin, LongMax, LongMin, ShortMax, ShortMin,
584 Uint16Max, Uint32Max, Uint8Max,
585 };
586 use mathematics::{
587 IsPrimeFunction, NextPrimeFunction, NthPrimeFunction, PrevPrimeFunction,
588 PrimeCountFunction, PrimeFunction, PrimePiFunction,
589 };
590 use trigonometry::{
591 AcosFunction, AsinFunction, Atan2Function, AtanFunction, CosFunction, CoshFunction,
592 CotFunction, SinFunction, SinhFunction, TanFunction, TanhFunction,
593 };
594
595 self.register(Box::new(PrimeFunction));
597 self.register(Box::new(NthPrimeFunction)); self.register(Box::new(IsPrimeFunction));
599 self.register(Box::new(PrimeCountFunction));
600 self.register(Box::new(PrimePiFunction)); self.register(Box::new(NextPrimeFunction));
602 self.register(Box::new(PrevPrimeFunction));
603
604 self.register(Box::new(SinFunction));
606 self.register(Box::new(CosFunction));
607 self.register(Box::new(TanFunction));
608 self.register(Box::new(CotFunction));
609 self.register(Box::new(AsinFunction));
610 self.register(Box::new(AcosFunction));
611 self.register(Box::new(AtanFunction));
612 self.register(Box::new(Atan2Function));
613
614 self.register(Box::new(SinhFunction));
616 self.register(Box::new(CoshFunction));
617 self.register(Box::new(TanhFunction));
618
619 self.register(Box::new(ToBase));
621 self.register(Box::new(FromBase));
622 self.register(Box::new(ToBinary));
623 self.register(Box::new(FromBinary));
624 self.register(Box::new(ToHex));
625 self.register(Box::new(FromHex));
626 self.register(Box::new(ToOctal));
627 self.register(Box::new(FromOctal));
628
629 self.register(Box::new(Int8Min));
631 self.register(Box::new(Int8Max));
632 self.register(Box::new(Uint8Max));
633 self.register(Box::new(Int16Min));
634 self.register(Box::new(Int16Max));
635 self.register(Box::new(Uint16Max));
636 self.register(Box::new(Int32Min));
637 self.register(Box::new(Int32Max));
638 self.register(Box::new(Uint32Max));
639 self.register(Box::new(Int64Min));
640 self.register(Box::new(Int64Max));
641
642 self.register(Box::new(ByteMin));
644 self.register(Box::new(ByteMax));
645 self.register(Box::new(CharMin));
646 self.register(Box::new(CharMax));
647 self.register(Box::new(ShortMin));
648 self.register(Box::new(ShortMax));
649 self.register(Box::new(IntMin));
650 self.register(Box::new(IntMax));
651 self.register(Box::new(LongMin));
652 self.register(Box::new(LongMax));
653
654 math::register_math_functions(self);
656 }
657
658 fn register_physics_functions(&mut self) {
660 physics::register_physics_functions(self);
661
662 use particle_charges::{
664 ChargeDownQuarkFunction, ChargeElectronFunction, ChargeMuonFunction,
665 ChargeNeutronFunction, ChargePositronFunction, ChargeProtonFunction, ChargeTauFunction,
666 ChargeUpQuarkFunction,
667 };
668
669 self.register(Box::new(ChargeElectronFunction));
670 self.register(Box::new(ChargeProtonFunction));
671 self.register(Box::new(ChargeNeutronFunction));
672 self.register(Box::new(ChargeUpQuarkFunction));
673 self.register(Box::new(ChargeDownQuarkFunction));
674 self.register(Box::new(ChargePositronFunction));
675 self.register(Box::new(ChargeMuonFunction));
676 self.register(Box::new(ChargeTauFunction));
677 }
678
679 fn register_date_time_functions(&mut self) {
681 date_time::register_date_time_functions(self);
682 }
683
684 fn register_financial_functions(&mut self) {
686 financial::register_financial_functions(self);
687 }
688
689 fn register_conversion_functions(&mut self) {
691 use convert::ConvertFunction;
692 use roman::{FromRoman, ToRoman};
693
694 self.register(Box::new(ConvertFunction));
695 self.register(Box::new(ToRoman));
696 self.register(Box::new(FromRoman));
697 }
698
699 fn register_statistical_functions(&mut self) {
701 use statistics::{
702 CorrelationFunction, KurtosisFunction, MedianFunction, ModeFunction,
703 PercentileFunction, SkewFunction, VarPopFunction, VarSampFunction, VarianceFunction,
704 };
705
706 self.register(Box::new(MedianFunction));
707 self.register(Box::new(PercentileFunction));
708 self.register(Box::new(ModeFunction));
709 self.register(Box::new(VarianceFunction));
710 self.register(Box::new(VarSampFunction));
711 self.register(Box::new(VarPopFunction));
712 self.register(Box::new(CorrelationFunction));
713 self.register(Box::new(SkewFunction));
714 self.register(Box::new(KurtosisFunction));
715 }
716
717 fn register_aggregate_functions(&mut self) {
719 use group_num::GroupNumFunction;
720
721 self.register(Box::new(GroupNumFunction::new()));
724 }
725
726 fn register_random_functions(&mut self) {
728 use random::{RandIntFunction, RandRangeFunction, RandomFunction};
729
730 self.register(Box::new(RandomFunction));
731 self.register(Box::new(RandIntFunction));
732 self.register(Box::new(RandRangeFunction));
733 }
734
735 fn register_format_functions(&mut self) {
737 use format::{
738 CenterFunction, FormatDateFunction, FormatNumberFunction, LPadFunction, RPadFunction,
739 };
740 use format_number::{FormatCurrencyFunction, RenderNumberFunction};
741
742 self.register(Box::new(FormatNumberFunction));
743 self.register(Box::new(FormatDateFunction));
744 self.register(Box::new(LPadFunction));
745 self.register(Box::new(RPadFunction));
746 self.register(Box::new(CenterFunction));
747 self.register(Box::new(RenderNumberFunction));
748 self.register(Box::new(FormatCurrencyFunction));
749 }
750
751 fn register_type_checking_functions(&mut self) {
753 use type_checking::{
754 IsBoolFunction, IsDateFunction, IsFloatFunction, IsIntegerFunction, IsNotNullFunction,
755 IsNullFunction, IsNumericFunction,
756 };
757
758 self.register(Box::new(IsDateFunction));
759 self.register(Box::new(IsBoolFunction));
760 self.register(Box::new(IsNumericFunction));
761 self.register(Box::new(IsIntegerFunction));
762 self.register(Box::new(IsFloatFunction));
763 self.register(Box::new(IsNullFunction));
764 self.register(Box::new(IsNotNullFunction));
765 }
766
767 fn register_utility_functions(&mut self) {
769 use utility::{
770 AsciiFunction, CharFunction, DecodeFunction, EncodeFunction, OrdFunction,
771 ToDecimalFunction, ToIntFunction, ToStringFunction, UnicodeFunction,
772 };
773
774 self.register(Box::new(AsciiFunction));
775 self.register(Box::new(OrdFunction));
776 self.register(Box::new(CharFunction));
777 self.register(Box::new(ToIntFunction));
778 self.register(Box::new(ToDecimalFunction));
779 self.register(Box::new(ToStringFunction));
780 self.register(Box::new(EncodeFunction));
781 self.register(Box::new(DecodeFunction));
782 self.register(Box::new(UnicodeFunction));
783 }
784
785 fn register_bigint_functions(&mut self) {
787 use bigint::{
788 BigAddFunction, BigFactorialFunction, BigIntFunction, BigMulFunction, BigPowFunction,
789 BitAndFunction, BitOrFunction, BitShiftFunction, BitXorFunction, FromBinaryFunction,
790 FromHexFunction, ToBinaryFunction, ToHexFunction,
791 };
792
793 self.register(Box::new(BigIntFunction));
795 self.register(Box::new(BigAddFunction));
796 self.register(Box::new(BigMulFunction));
797 self.register(Box::new(BigPowFunction));
798 self.register(Box::new(BigFactorialFunction));
799
800 self.register(Box::new(BitAndFunction));
802 self.register(Box::new(BitOrFunction));
803 self.register(Box::new(BitXorFunction));
804 self.register(Box::new(BitShiftFunction));
805
806 self.register(Box::new(ToBinaryFunction));
808 self.register(Box::new(FromBinaryFunction));
809 self.register(Box::new(ToHexFunction));
810 self.register(Box::new(FromHexFunction));
811 }
812}
813
814impl Default for FunctionRegistry {
815 fn default() -> Self {
816 Self::new()
817 }
818}
819
820#[cfg(test)]
821mod tests {
822 use super::*;
823
824 #[test]
825 fn test_registry_creation() {
826 let registry = FunctionRegistry::new();
827
828 assert!(registry.contains("PI"));
830 assert!(registry.contains("MASS_EARTH"));
831 assert!(registry.contains("ME"));
832 }
833
834 #[test]
835 fn test_case_insensitive_lookup() {
836 let registry = FunctionRegistry::new();
837
838 assert!(registry.get("pi").is_some());
839 assert!(registry.get("PI").is_some());
840 assert!(registry.get("Pi").is_some());
841 }
842
843 #[test]
844 fn test_autocomplete() {
845 let registry = FunctionRegistry::new();
846
847 let mass_functions = registry.autocomplete("MASS");
848 assert!(!mass_functions.is_empty());
849
850 let names: Vec<&str> = mass_functions.iter().map(|sig| sig.name).collect();
852 assert!(names.contains(&"MASS_EARTH"));
853 assert!(names.contains(&"MASS_SUN"));
854 }
855}