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 fn register_math_functions(registry: &mut super::FunctionRegistry) {
739 registry.register(Box::new(RoundFunction));
740 registry.register(Box::new(AbsFunction));
741 registry.register(Box::new(FloorFunction));
742 registry.register(Box::new(CeilingFunction));
743 registry.register(Box::new(CeilFunction)); registry.register(Box::new(ModFunction));
745 registry.register(Box::new(QuotientFunction));
746 registry.register(Box::new(SqrtFunction));
747 registry.register(Box::new(ExpFunction));
748 registry.register(Box::new(LnFunction));
749 registry.register(Box::new(LogFunction));
750 registry.register(Box::new(Log10Function));
751 registry.register(Box::new(PowerFunction));
752 registry.register(Box::new(PowFunction)); registry.register(Box::new(DegreesFunction));
754 registry.register(Box::new(RadiansFunction));
755 registry.register(Box::new(FactorialFunction));
756 registry.register(Box::new(SumNFunction));
757}