1use anyhow::{anyhow, Result};
2
3use crate::data::datatable::DataValue;
4use crate::sql::functions::{ArgCount, FunctionCategory, FunctionSignature, SqlFunction};
5
6pub struct RoundFunction;
8
9impl SqlFunction for RoundFunction {
10 fn signature(&self) -> FunctionSignature {
11 FunctionSignature {
12 name: "ROUND",
13 category: FunctionCategory::Mathematical,
14 arg_count: ArgCount::Range(1, 2),
15 description: "Round a number to specified decimal places",
16 returns: "NUMBER",
17 examples: vec![
18 "SELECT ROUND(3.14159, 2)", "SELECT ROUND(123.456)", "SELECT ROUND(1234.5, -2)", ],
22 }
23 }
24
25 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
26 self.validate_args(args)?;
27
28 let value = match &args[0] {
29 DataValue::Integer(n) => *n as f64,
30 DataValue::Float(f) => *f,
31 DataValue::Null => return Ok(DataValue::Null),
32 _ => return Err(anyhow!("ROUND requires a numeric argument")),
33 };
34
35 let decimals = if args.len() == 2 {
36 match &args[1] {
37 DataValue::Integer(n) => *n as i32,
38 DataValue::Float(f) => *f as i32,
39 _ => return Err(anyhow!("ROUND precision must be a number")),
40 }
41 } else {
42 0
43 };
44
45 if decimals >= 0 {
46 let multiplier = 10_f64.powi(decimals);
47 let rounded = (value * multiplier).round() / multiplier;
48
49 if decimals == 0 {
51 Ok(DataValue::Integer(rounded as i64))
52 } else if matches!(&args[0], DataValue::Integer(_)) && rounded == value {
53 Ok(DataValue::Integer(value as i64))
55 } else {
56 Ok(DataValue::Float(rounded))
57 }
58 } else {
59 let divisor = 10_f64.powi(-decimals);
61 let rounded = (value / divisor).round() * divisor;
62 Ok(DataValue::Float(rounded))
63 }
64 }
65}
66
67pub struct AbsFunction;
69
70impl SqlFunction for AbsFunction {
71 fn signature(&self) -> FunctionSignature {
72 FunctionSignature {
73 name: "ABS",
74 category: FunctionCategory::Mathematical,
75 arg_count: ArgCount::Fixed(1),
76 description: "Returns the absolute value of a number",
77 returns: "NUMBER",
78 examples: vec![
79 "SELECT ABS(-5)", "SELECT ABS(3.14)", "SELECT ABS(price - cost) FROM products",
82 ],
83 }
84 }
85
86 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
87 self.validate_args(args)?;
88
89 match &args[0] {
90 DataValue::Integer(n) => Ok(DataValue::Integer(n.abs())),
91 DataValue::Float(f) => Ok(DataValue::Float(f.abs())),
92 DataValue::Null => Ok(DataValue::Null),
93 _ => Err(anyhow!("ABS requires a numeric argument")),
94 }
95 }
96}
97
98pub struct FloorFunction;
100
101impl SqlFunction for FloorFunction {
102 fn signature(&self) -> FunctionSignature {
103 FunctionSignature {
104 name: "FLOOR",
105 category: FunctionCategory::Mathematical,
106 arg_count: ArgCount::Fixed(1),
107 description: "Returns the largest integer less than or equal to the value",
108 returns: "INTEGER",
109 examples: vec![
110 "SELECT FLOOR(3.7)", "SELECT FLOOR(-2.3)", "SELECT FLOOR(5)", ],
114 }
115 }
116
117 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
118 self.validate_args(args)?;
119
120 match &args[0] {
121 DataValue::Integer(n) => Ok(DataValue::Integer(*n)),
122 DataValue::Float(f) => Ok(DataValue::Integer(f.floor() as i64)),
123 DataValue::Null => Ok(DataValue::Null),
124 _ => Err(anyhow!("FLOOR requires a numeric argument")),
125 }
126 }
127}
128
129pub struct CeilingFunction;
131
132impl SqlFunction for CeilingFunction {
133 fn signature(&self) -> FunctionSignature {
134 FunctionSignature {
135 name: "CEILING",
136 category: FunctionCategory::Mathematical,
137 arg_count: ArgCount::Fixed(1),
138 description: "Returns the smallest integer greater than or equal to the value",
139 returns: "INTEGER",
140 examples: vec![
141 "SELECT CEILING(3.2)", "SELECT CEILING(-2.7)", "SELECT CEILING(5)", ],
145 }
146 }
147
148 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
149 self.validate_args(args)?;
150
151 match &args[0] {
152 DataValue::Integer(n) => Ok(DataValue::Integer(*n)),
153 DataValue::Float(f) => Ok(DataValue::Integer(f.ceil() as i64)),
154 DataValue::Null => Ok(DataValue::Null),
155 _ => Err(anyhow!("CEILING requires a numeric argument")),
156 }
157 }
158}
159
160pub struct CeilFunction;
162
163impl SqlFunction for CeilFunction {
164 fn signature(&self) -> FunctionSignature {
165 FunctionSignature {
166 name: "CEIL",
167 category: FunctionCategory::Mathematical,
168 arg_count: ArgCount::Fixed(1),
169 description: "Alias for CEILING - Returns the smallest integer greater than or equal to the value",
170 returns: "INTEGER",
171 examples: vec![
172 "SELECT CEIL(3.2)", "SELECT CEIL(-2.7)", "SELECT CEIL(5)", ],
176 }
177 }
178
179 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
180 let ceiling_func = CeilingFunction;
182 ceiling_func.evaluate(args)
183 }
184}
185
186pub struct ModFunction;
188
189impl SqlFunction for ModFunction {
190 fn signature(&self) -> FunctionSignature {
191 FunctionSignature {
192 name: "MOD",
193 category: FunctionCategory::Mathematical,
194 arg_count: ArgCount::Fixed(2),
195 description: "Returns the remainder of division",
196 returns: "NUMBER",
197 examples: vec![
198 "SELECT MOD(10, 3)", "SELECT MOD(15, 4)", "SELECT MOD(id, 100) FROM table",
201 ],
202 }
203 }
204
205 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
206 self.validate_args(args)?;
207
208 let dividend = match &args[0] {
209 DataValue::Integer(n) => *n as f64,
210 DataValue::Float(f) => *f,
211 DataValue::Null => return Ok(DataValue::Null),
212 _ => return Err(anyhow!("MOD requires numeric arguments")),
213 };
214
215 let divisor = match &args[1] {
216 DataValue::Integer(n) => *n as f64,
217 DataValue::Float(f) => *f,
218 DataValue::Null => return Ok(DataValue::Null),
219 _ => return Err(anyhow!("MOD requires numeric arguments")),
220 };
221
222 if divisor == 0.0 {
223 return Err(anyhow!("Division by zero in MOD"));
224 }
225
226 let both_integers =
228 matches!(&args[0], DataValue::Integer(_)) && matches!(&args[1], DataValue::Integer(_));
229
230 let result = dividend % divisor;
231
232 if both_integers && result.fract() == 0.0 {
233 Ok(DataValue::Integer(result as i64))
234 } else {
235 Ok(DataValue::Float(result))
236 }
237 }
238}
239
240pub struct QuotientFunction;
242
243impl SqlFunction for QuotientFunction {
244 fn signature(&self) -> FunctionSignature {
245 FunctionSignature {
246 name: "QUOTIENT",
247 category: FunctionCategory::Mathematical,
248 arg_count: ArgCount::Fixed(2),
249 description: "Returns the integer portion of division",
250 returns: "INTEGER",
251 examples: vec![
252 "SELECT QUOTIENT(10, 3)", "SELECT QUOTIENT(15, 4)", "SELECT QUOTIENT(100, 7)", ],
256 }
257 }
258
259 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
260 self.validate_args(args)?;
261
262 let numerator = match &args[0] {
263 DataValue::Integer(n) => *n as f64,
264 DataValue::Float(f) => *f,
265 DataValue::Null => return Ok(DataValue::Null),
266 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
267 };
268
269 let denominator = match &args[1] {
270 DataValue::Integer(n) => *n as f64,
271 DataValue::Float(f) => *f,
272 DataValue::Null => return Ok(DataValue::Null),
273 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
274 };
275
276 if denominator == 0.0 {
277 return Err(anyhow!("Division by zero in QUOTIENT"));
278 }
279
280 Ok(DataValue::Integer((numerator / denominator).trunc() as i64))
281 }
282}
283
284pub struct SqrtFunction;
286
287impl SqlFunction for SqrtFunction {
288 fn signature(&self) -> FunctionSignature {
289 FunctionSignature {
290 name: "SQRT",
291 category: FunctionCategory::Mathematical,
292 arg_count: ArgCount::Fixed(1),
293 description: "Returns the square root of a number",
294 returns: "FLOAT",
295 examples: vec![
296 "SELECT SQRT(16)", "SELECT SQRT(2)", "SELECT SQRT(area) FROM squares",
299 ],
300 }
301 }
302
303 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
304 self.validate_args(args)?;
305
306 let value = match &args[0] {
307 DataValue::Integer(n) => *n as f64,
308 DataValue::Float(f) => *f,
309 DataValue::Null => return Ok(DataValue::Null),
310 _ => return Err(anyhow!("SQRT requires a numeric argument")),
311 };
312
313 if value < 0.0 {
314 return Err(anyhow!("SQRT of negative number"));
315 }
316
317 Ok(DataValue::Float(value.sqrt()))
318 }
319}
320
321pub struct ExpFunction;
323
324impl SqlFunction for ExpFunction {
325 fn signature(&self) -> FunctionSignature {
326 FunctionSignature {
327 name: "EXP",
328 category: FunctionCategory::Mathematical,
329 arg_count: ArgCount::Fixed(1),
330 description: "Returns e raised to the power of the given number",
331 returns: "FLOAT",
332 examples: vec![
333 "SELECT EXP(1)", "SELECT EXP(0)", "SELECT EXP(LN(10))", ],
337 }
338 }
339
340 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
341 self.validate_args(args)?;
342
343 let value = match &args[0] {
344 DataValue::Integer(n) => *n as f64,
345 DataValue::Float(f) => *f,
346 DataValue::Null => return Ok(DataValue::Null),
347 _ => return Err(anyhow!("EXP requires a numeric argument")),
348 };
349
350 Ok(DataValue::Float(value.exp()))
351 }
352}
353
354pub struct LnFunction;
356
357impl SqlFunction for LnFunction {
358 fn signature(&self) -> FunctionSignature {
359 FunctionSignature {
360 name: "LN",
361 category: FunctionCategory::Mathematical,
362 arg_count: ArgCount::Fixed(1),
363 description: "Returns the natural logarithm (base e) of a number",
364 returns: "FLOAT",
365 examples: vec![
366 "SELECT LN(2.718282)", "SELECT LN(10)", "SELECT LN(1)", ],
370 }
371 }
372
373 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
374 self.validate_args(args)?;
375
376 let value = match &args[0] {
377 DataValue::Integer(n) => *n as f64,
378 DataValue::Float(f) => *f,
379 DataValue::Null => return Ok(DataValue::Null),
380 _ => return Err(anyhow!("LN requires a numeric argument")),
381 };
382
383 if value <= 0.0 {
384 return Err(anyhow!("LN of non-positive number"));
385 }
386
387 Ok(DataValue::Float(value.ln()))
388 }
389}
390
391pub struct LogFunction;
393
394impl SqlFunction for LogFunction {
395 fn signature(&self) -> FunctionSignature {
396 FunctionSignature {
397 name: "LOG",
398 category: FunctionCategory::Mathematical,
399 arg_count: ArgCount::Range(1, 2),
400 description:
401 "Returns the logarithm of a number (base 10 by default, or specified base)",
402 returns: "FLOAT",
403 examples: vec![
404 "SELECT LOG(100)", "SELECT LOG(8, 2)", "SELECT LOG(1000, 10)", ],
408 }
409 }
410
411 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
412 self.validate_args(args)?;
413
414 let value = match &args[0] {
415 DataValue::Integer(n) => *n as f64,
416 DataValue::Float(f) => *f,
417 DataValue::Null => return Ok(DataValue::Null),
418 _ => return Err(anyhow!("LOG requires numeric arguments")),
419 };
420
421 if value <= 0.0 {
422 return Err(anyhow!("LOG of non-positive number"));
423 }
424
425 let base = if args.len() == 2 {
426 match &args[1] {
427 DataValue::Integer(n) => *n as f64,
428 DataValue::Float(f) => *f,
429 _ => return Err(anyhow!("LOG base must be a number")),
430 }
431 } else {
432 10.0
433 };
434
435 if base <= 0.0 || base == 1.0 {
436 return Err(anyhow!("Invalid logarithm base"));
437 }
438
439 Ok(DataValue::Float(value.log(base)))
440 }
441}
442
443pub struct Log10Function;
445
446impl SqlFunction for Log10Function {
447 fn signature(&self) -> FunctionSignature {
448 FunctionSignature {
449 name: "LOG10",
450 category: FunctionCategory::Mathematical,
451 arg_count: ArgCount::Fixed(1),
452 description: "Returns the base-10 logarithm of a number",
453 returns: "FLOAT",
454 examples: vec![
455 "SELECT LOG10(100)", "SELECT LOG10(1000)", "SELECT LOG10(0.1)", ],
459 }
460 }
461
462 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
463 self.validate_args(args)?;
464
465 let value = match &args[0] {
466 DataValue::Integer(n) => *n as f64,
467 DataValue::Float(f) => *f,
468 DataValue::Null => return Ok(DataValue::Null),
469 _ => return Err(anyhow!("LOG10 requires a numeric argument")),
470 };
471
472 if value <= 0.0 {
473 return Err(anyhow!("LOG10 of non-positive number"));
474 }
475
476 Ok(DataValue::Float(value.log10()))
477 }
478}
479
480pub struct PowerFunction;
482
483impl SqlFunction for PowerFunction {
484 fn signature(&self) -> FunctionSignature {
485 FunctionSignature {
486 name: "POWER",
487 category: FunctionCategory::Mathematical,
488 arg_count: ArgCount::Fixed(2),
489 description: "Returns a number raised to a power",
490 returns: "NUMBER",
491 examples: vec![
492 "SELECT POWER(2, 3)", "SELECT POWER(10, -2)", "SELECT POWER(9, 0.5)", ],
496 }
497 }
498
499 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
500 self.validate_args(args)?;
501
502 let base = match &args[0] {
503 DataValue::Integer(n) => *n as f64,
504 DataValue::Float(f) => *f,
505 DataValue::Null => return Ok(DataValue::Null),
506 _ => return Err(anyhow!("POWER requires numeric arguments")),
507 };
508
509 let exponent = match &args[1] {
510 DataValue::Integer(n) => *n as f64,
511 DataValue::Float(f) => *f,
512 DataValue::Null => return Ok(DataValue::Null),
513 _ => return Err(anyhow!("POWER requires numeric arguments")),
514 };
515
516 let result = base.powf(exponent);
517
518 Ok(DataValue::Float(result))
520 }
521}
522
523pub struct PowFunction;
525
526impl SqlFunction for PowFunction {
527 fn signature(&self) -> FunctionSignature {
528 FunctionSignature {
529 name: "POW",
530 category: FunctionCategory::Mathematical,
531 arg_count: ArgCount::Fixed(2),
532 description: "Returns a number raised to a power (alias for POWER)",
533 returns: "FLOAT",
534 examples: vec![
535 "SELECT POW(2, 3)", "SELECT POW(10, -2)", "SELECT POW(9, 0.5)", ],
539 }
540 }
541
542 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
543 let power_func = PowerFunction;
545 power_func.evaluate(args)
546 }
547}
548
549pub struct DegreesFunction;
551
552impl SqlFunction for DegreesFunction {
553 fn signature(&self) -> FunctionSignature {
554 FunctionSignature {
555 name: "DEGREES",
556 category: FunctionCategory::Mathematical,
557 arg_count: ArgCount::Fixed(1),
558 description: "Convert radians to degrees",
559 returns: "FLOAT",
560 examples: vec![
561 "SELECT DEGREES(PI())", "SELECT DEGREES(PI()/2)", "SELECT DEGREES(1)", ],
565 }
566 }
567
568 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
569 self.validate_args(args)?;
570
571 let radians = match &args[0] {
572 DataValue::Integer(n) => *n as f64,
573 DataValue::Float(f) => *f,
574 DataValue::Null => return Ok(DataValue::Null),
575 _ => return Err(anyhow!("DEGREES requires a numeric argument")),
576 };
577
578 Ok(DataValue::Float(radians * 180.0 / std::f64::consts::PI))
579 }
580}
581
582pub struct RadiansFunction;
584
585impl SqlFunction for RadiansFunction {
586 fn signature(&self) -> FunctionSignature {
587 FunctionSignature {
588 name: "RADIANS",
589 category: FunctionCategory::Mathematical,
590 arg_count: ArgCount::Fixed(1),
591 description: "Convert degrees to radians",
592 returns: "FLOAT",
593 examples: vec![
594 "SELECT RADIANS(180)", "SELECT RADIANS(90)", "SELECT RADIANS(45)", ],
598 }
599 }
600
601 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
602 self.validate_args(args)?;
603
604 let degrees = match &args[0] {
605 DataValue::Integer(n) => *n as f64,
606 DataValue::Float(f) => *f,
607 DataValue::Null => return Ok(DataValue::Null),
608 _ => return Err(anyhow!("RADIANS requires a numeric argument")),
609 };
610
611 Ok(DataValue::Float(degrees * std::f64::consts::PI / 180.0))
612 }
613}
614
615pub struct FactorialFunction;
617
618impl FactorialFunction {
619 const FACTORIAL_TABLE: [u64; 21] = [
622 1, 1, 2, 6, 24, 120, 720, 5_040, 40_320, 362_880, 3_628_800, 39_916_800, 479_001_600, 6_227_020_800, 87_178_291_200, 1_307_674_368_000, 20_922_789_888_000, 355_687_428_096_000, 6_402_373_705_728_000, 121_645_100_408_832_000, 2_432_902_008_176_640_000, ];
644
645 fn factorial(n: u64) -> Result<u64> {
646 if n <= 20 {
647 Ok(Self::FACTORIAL_TABLE[n as usize])
648 } else {
649 Err(anyhow!("FACTORIAL: argument {} too large (max is 20)", n))
650 }
651 }
652}
653
654impl SqlFunction for FactorialFunction {
655 fn signature(&self) -> FunctionSignature {
656 FunctionSignature {
657 name: "FACTORIAL",
658 category: FunctionCategory::Mathematical,
659 arg_count: ArgCount::Fixed(1),
660 description: "Returns the factorial of a non-negative integer (n!)",
661 returns: "INTEGER",
662 examples: vec![
663 "SELECT FACTORIAL(5)", "SELECT FACTORIAL(10)", "SELECT FACTORIAL(0)", ],
667 }
668 }
669
670 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
671 self.validate_args(args)?;
672
673 let n = match &args[0] {
674 DataValue::Integer(i) if *i >= 0 && *i <= 20 => *i as u64,
675 DataValue::Integer(i) if *i < 0 => {
676 return Err(anyhow!("FACTORIAL requires a non-negative integer"))
677 }
678 DataValue::Integer(i) => {
679 return Err(anyhow!("FACTORIAL: argument {} too large (max is 20)", i))
680 }
681 DataValue::Float(f) if f.is_finite() && *f >= 0.0 && f.floor() == *f => {
682 let n = *f as i64;
683 if n > 20 {
684 return Err(anyhow!("FACTORIAL: argument {} too large (max is 20)", n));
685 }
686 n as u64
687 }
688 DataValue::Null => return Ok(DataValue::Null),
689 _ => return Err(anyhow!("FACTORIAL requires a non-negative integer")),
690 };
691
692 Ok(DataValue::Integer(Self::factorial(n)? as i64))
693 }
694}
695
696pub struct SumNFunction;
698
699impl SqlFunction for SumNFunction {
700 fn signature(&self) -> FunctionSignature {
701 FunctionSignature {
702 name: "SUM_N",
703 category: FunctionCategory::Mathematical,
704 arg_count: ArgCount::Fixed(1),
705 description: "Calculate sum of first n natural numbers (triangular number)",
706 returns: "INTEGER",
707 examples: vec![
708 "SELECT SUM_N(10)", "SELECT SUM_N(100)", "SELECT SUM_N(5)", ],
712 }
713 }
714
715 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
716 self.validate_args(args)?;
717
718 let n = match &args[0] {
719 DataValue::Integer(n) if *n >= 0 => *n,
720 DataValue::Float(f) if f.is_finite() && *f >= 0.0 && f.floor() == *f => *f as i64,
721 DataValue::Null => return Ok(DataValue::Null),
722 _ => return Err(anyhow!("SUM_N requires a non-negative integer")),
723 };
724
725 if n > 3037000499 {
728 return Err(anyhow!("SUM_N: argument {} too large (would overflow)", n));
730 }
731
732 let result = n * (n + 1) / 2;
733 Ok(DataValue::Integer(result))
734 }
735}
736
737pub struct SumNSqrFunction;
739
740impl SqlFunction for SumNSqrFunction {
741 fn signature(&self) -> FunctionSignature {
742 FunctionSignature {
743 name: "SUM_N_SQR",
744 category: FunctionCategory::Mathematical,
745 arg_count: ArgCount::Fixed(1),
746 description: "Sum of squares from 1 to n: 1² + 2² + ... + n²",
747 returns: "Integer - sum of squares (n(n+1)(2n+1)/6)",
748 examples: vec![
749 "SELECT SUM_N_SQR(5) -- Returns 55 (1+4+9+16+25)",
750 "SELECT SUM_N_SQR(10) -- Returns 385",
751 ],
752 }
753 }
754
755 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
756 if args.len() != 1 {
757 return Err(anyhow!("SUM_N_SQR requires exactly 1 argument"));
758 }
759
760 let n = match &args[0] {
761 DataValue::Integer(i) => *i,
762 DataValue::Float(f) => *f as i64,
763 _ => return Err(anyhow!("SUM_N_SQR requires a numeric argument")),
764 };
765
766 if n < 0 {
767 return Err(anyhow!("SUM_N_SQR requires a non-negative number"));
768 }
769
770 let result = n * (n + 1) * (2 * n + 1) / 6;
772 Ok(DataValue::Integer(result))
773 }
774}
775
776pub struct SumNCubeFunction;
778
779impl SqlFunction for SumNCubeFunction {
780 fn signature(&self) -> FunctionSignature {
781 FunctionSignature {
782 name: "SUM_N_CUBE",
783 category: FunctionCategory::Mathematical,
784 arg_count: ArgCount::Fixed(1),
785 description: "Sum of cubes from 1 to n: 1³ + 2³ + ... + n³",
786 returns: "Integer - sum of cubes ([n(n+1)/2]²)",
787 examples: vec![
788 "SELECT SUM_N_CUBE(4) -- Returns 100 (1+8+27+64)",
789 "SELECT SUM_N_CUBE(5) -- Returns 225",
790 ],
791 }
792 }
793
794 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
795 if args.len() != 1 {
796 return Err(anyhow!("SUM_N_CUBE requires exactly 1 argument"));
797 }
798
799 let n = match &args[0] {
800 DataValue::Integer(i) => *i,
801 DataValue::Float(f) => *f as i64,
802 _ => return Err(anyhow!("SUM_N_CUBE requires a numeric argument")),
803 };
804
805 if n < 0 {
806 return Err(anyhow!("SUM_N_CUBE requires a non-negative number"));
807 }
808
809 let sum_n = n * (n + 1) / 2;
811 let result = sum_n * sum_n;
812 Ok(DataValue::Integer(result))
813 }
814}
815
816pub struct HarmonicFunction;
818
819impl SqlFunction for HarmonicFunction {
820 fn signature(&self) -> FunctionSignature {
821 FunctionSignature {
822 name: "HARMONIC",
823 category: FunctionCategory::Mathematical,
824 arg_count: ArgCount::Fixed(1),
825 description: "Harmonic series: 1 + 1/2 + 1/3 + ... + 1/n",
826 returns: "Float - sum of harmonic series",
827 examples: vec![
828 "SELECT HARMONIC(4) -- Returns 2.0833... (1 + 0.5 + 0.333... + 0.25)",
829 "SELECT HARMONIC(10) -- Returns 2.9290...",
830 ],
831 }
832 }
833
834 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
835 if args.len() != 1 {
836 return Err(anyhow!("HARMONIC requires exactly 1 argument"));
837 }
838
839 let n = match &args[0] {
840 DataValue::Integer(i) => *i,
841 DataValue::Float(f) => *f as i64,
842 _ => return Err(anyhow!("HARMONIC requires a numeric argument")),
843 };
844
845 if n <= 0 {
846 return Err(anyhow!("HARMONIC requires a positive number"));
847 }
848
849 let mut sum = 0.0;
850 for i in 1..=n {
851 sum += 1.0 / i as f64;
852 }
853
854 Ok(DataValue::Float(sum))
855 }
856}
857
858pub struct FibonacciFunction;
860
861impl SqlFunction for FibonacciFunction {
862 fn signature(&self) -> FunctionSignature {
863 FunctionSignature {
864 name: "FIBONACCI",
865 category: FunctionCategory::Mathematical,
866 arg_count: ArgCount::Fixed(1),
867 description: "Returns the nth Fibonacci number (0, 1, 1, 2, 3, 5, 8, ...)",
868 returns: "Integer - nth Fibonacci number",
869 examples: vec![
870 "SELECT FIBONACCI(7) -- Returns 13",
871 "SELECT FIBONACCI(10) -- Returns 55",
872 ],
873 }
874 }
875
876 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
877 if args.len() != 1 {
878 return Err(anyhow!("FIBONACCI requires exactly 1 argument"));
879 }
880
881 let n = match &args[0] {
882 DataValue::Integer(i) => *i,
883 DataValue::Float(f) => *f as i64,
884 _ => return Err(anyhow!("FIBONACCI requires a numeric argument")),
885 };
886
887 if n < 0 {
888 return Err(anyhow!("FIBONACCI requires a non-negative number"));
889 }
890
891 if n == 0 {
892 return Ok(DataValue::Integer(0));
893 }
894 if n == 1 {
895 return Ok(DataValue::Integer(1));
896 }
897
898 let mut a = 0i64;
899 let mut b = 1i64;
900
901 for _ in 2..=n {
902 let temp = a + b;
903 a = b;
904 b = temp;
905 }
906
907 Ok(DataValue::Integer(b))
908 }
909}
910
911pub struct GeometricFunction;
913
914impl SqlFunction for GeometricFunction {
915 fn signature(&self) -> FunctionSignature {
916 FunctionSignature {
917 name: "GEOMETRIC",
918 category: FunctionCategory::Mathematical,
919 arg_count: ArgCount::Fixed(3),
920 description: "Geometric series sum: a + ar + ar² + ... + ar^(n-1)",
921 returns: "Float - sum of geometric series",
922 examples: vec![
923 "SELECT GEOMETRIC(1, 2, 5) -- Returns 31 (1 + 2 + 4 + 8 + 16)",
924 "SELECT GEOMETRIC(1, 0.5, 10) -- Returns 1.998... (converging series)",
925 ],
926 }
927 }
928
929 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
930 if args.len() != 3 {
931 return Err(anyhow!("GEOMETRIC requires exactly 3 arguments (a, r, n)"));
932 }
933
934 let a = match &args[0] {
935 DataValue::Integer(i) => *i as f64,
936 DataValue::Float(f) => *f,
937 _ => return Err(anyhow!("GEOMETRIC first argument (a) must be numeric")),
938 };
939
940 let r = match &args[1] {
941 DataValue::Integer(i) => *i as f64,
942 DataValue::Float(f) => *f,
943 _ => return Err(anyhow!("GEOMETRIC second argument (r) must be numeric")),
944 };
945
946 let n = match &args[2] {
947 DataValue::Integer(i) => *i,
948 DataValue::Float(f) => *f as i64,
949 _ => return Err(anyhow!("GEOMETRIC third argument (n) must be numeric")),
950 };
951
952 if n < 0 {
953 return Err(anyhow!("GEOMETRIC requires non-negative n"));
954 }
955
956 if n == 0 {
957 return Ok(DataValue::Float(0.0));
958 }
959
960 let sum = if (r - 1.0).abs() < 1e-10 {
963 a * n as f64
964 } else {
965 a * (1.0 - r.powi(n as i32)) / (1.0 - r)
966 };
967
968 Ok(DataValue::Float(sum))
969 }
970}
971
972pub fn register_math_functions(registry: &mut super::FunctionRegistry) {
974 registry.register(Box::new(RoundFunction));
975 registry.register(Box::new(AbsFunction));
976 registry.register(Box::new(FloorFunction));
977 registry.register(Box::new(CeilingFunction));
978 registry.register(Box::new(CeilFunction)); registry.register(Box::new(ModFunction));
980 registry.register(Box::new(QuotientFunction));
981 registry.register(Box::new(SqrtFunction));
982 registry.register(Box::new(ExpFunction));
983 registry.register(Box::new(LnFunction));
984 registry.register(Box::new(LogFunction));
985 registry.register(Box::new(Log10Function));
986 registry.register(Box::new(PowerFunction));
987 registry.register(Box::new(PowFunction)); registry.register(Box::new(DegreesFunction));
989 registry.register(Box::new(RadiansFunction));
990 registry.register(Box::new(FactorialFunction));
991 registry.register(Box::new(SumNFunction));
992 registry.register(Box::new(SumNSqrFunction));
993 registry.register(Box::new(SumNCubeFunction));
994 registry.register(Box::new(HarmonicFunction));
995 registry.register(Box::new(FibonacciFunction));
996 registry.register(Box::new(GeometricFunction));
997}