1use crate::data::datatable::{DataTable, DataValue};
2use crate::sql::recursive_parser::SqlExpression;
3use anyhow::{anyhow, Result};
4use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, TimeZone, Utc};
5use tracing::debug;
6
7pub struct ArithmeticEvaluator<'a> {
10 table: &'a DataTable,
11 date_notation: String,
12}
13
14impl<'a> ArithmeticEvaluator<'a> {
15 pub fn new(table: &'a DataTable) -> Self {
16 Self {
17 table,
18 date_notation: "us".to_string(),
19 }
20 }
21
22 pub fn with_date_notation(table: &'a DataTable, date_notation: String) -> Self {
23 Self {
24 table,
25 date_notation,
26 }
27 }
28
29 fn find_similar_column(&self, name: &str) -> Option<String> {
31 let columns = self.table.column_names();
32 let mut best_match: Option<(String, usize)> = None;
33
34 for col in columns {
35 let distance = self.edit_distance(&col.to_lowercase(), &name.to_lowercase());
36 let max_distance = if name.len() > 10 { 3 } else { 2 };
39 if distance <= max_distance {
40 match &best_match {
41 None => best_match = Some((col, distance)),
42 Some((_, best_dist)) if distance < *best_dist => {
43 best_match = Some((col, distance));
44 }
45 _ => {}
46 }
47 }
48 }
49
50 best_match.map(|(name, _)| name)
51 }
52
53 fn edit_distance(&self, s1: &str, s2: &str) -> usize {
55 let len1 = s1.len();
56 let len2 = s2.len();
57 let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];
58
59 for i in 0..=len1 {
60 matrix[i][0] = i;
61 }
62 for j in 0..=len2 {
63 matrix[0][j] = j;
64 }
65
66 for (i, c1) in s1.chars().enumerate() {
67 for (j, c2) in s2.chars().enumerate() {
68 let cost = if c1 == c2 { 0 } else { 1 };
69 matrix[i + 1][j + 1] = std::cmp::min(
70 matrix[i][j + 1] + 1, std::cmp::min(
72 matrix[i + 1][j] + 1, matrix[i][j] + cost, ),
75 );
76 }
77 }
78
79 matrix[len1][len2]
80 }
81
82 pub fn evaluate(&self, expr: &SqlExpression, row_index: usize) -> Result<DataValue> {
84 debug!(
85 "ArithmeticEvaluator: evaluating {:?} for row {}",
86 expr, row_index
87 );
88
89 match expr {
90 SqlExpression::Column(column_name) => self.evaluate_column(column_name, row_index),
91 SqlExpression::StringLiteral(s) => Ok(DataValue::String(s.clone())),
92 SqlExpression::NumberLiteral(n) => self.evaluate_number_literal(n),
93 SqlExpression::BinaryOp { left, op, right } => {
94 self.evaluate_binary_op(left, op, right, row_index)
95 }
96 SqlExpression::FunctionCall { name, args } => {
97 self.evaluate_function(name, args, row_index)
98 }
99 SqlExpression::MethodCall {
100 object,
101 method,
102 args,
103 } => self.evaluate_method_call(object, method, args, row_index),
104 SqlExpression::ChainedMethodCall { base, method, args } => {
105 let base_value = self.evaluate(base, row_index)?;
107 self.evaluate_method_on_value(&base_value, method, args, row_index)
108 }
109 SqlExpression::CaseExpression {
110 when_branches,
111 else_branch,
112 } => self.evaluate_case_expression(when_branches, else_branch, row_index),
113 _ => Err(anyhow!(
114 "Unsupported expression type for arithmetic evaluation: {:?}",
115 expr
116 )),
117 }
118 }
119
120 fn evaluate_column(&self, column_name: &str, row_index: usize) -> Result<DataValue> {
122 let col_index = self.table.get_column_index(column_name).ok_or_else(|| {
123 let suggestion = self.find_similar_column(column_name);
124 match suggestion {
125 Some(similar) => anyhow!(
126 "Column '{}' not found. Did you mean '{}'?",
127 column_name,
128 similar
129 ),
130 None => anyhow!("Column '{}' not found", column_name),
131 }
132 })?;
133
134 if row_index >= self.table.row_count() {
135 return Err(anyhow!("Row index {} out of bounds", row_index));
136 }
137
138 let row = self
139 .table
140 .get_row(row_index)
141 .ok_or_else(|| anyhow!("Row {} not found", row_index))?;
142
143 let value = row
144 .get(col_index)
145 .ok_or_else(|| anyhow!("Column index {} out of bounds for row", col_index))?;
146
147 Ok(value.clone())
148 }
149
150 fn evaluate_number_literal(&self, number_str: &str) -> Result<DataValue> {
152 if let Ok(int_val) = number_str.parse::<i64>() {
154 return Ok(DataValue::Integer(int_val));
155 }
156
157 if let Ok(float_val) = number_str.parse::<f64>() {
159 return Ok(DataValue::Float(float_val));
160 }
161
162 Err(anyhow!("Invalid number literal: {}", number_str))
163 }
164
165 fn evaluate_binary_op(
167 &self,
168 left: &SqlExpression,
169 op: &str,
170 right: &SqlExpression,
171 row_index: usize,
172 ) -> Result<DataValue> {
173 let left_val = self.evaluate(left, row_index)?;
174 let right_val = self.evaluate(right, row_index)?;
175
176 debug!(
177 "ArithmeticEvaluator: {} {} {}",
178 self.format_value(&left_val),
179 op,
180 self.format_value(&right_val)
181 );
182
183 match op {
184 "+" => self.add_values(&left_val, &right_val),
185 "-" => self.subtract_values(&left_val, &right_val),
186 "*" => self.multiply_values(&left_val, &right_val),
187 "/" => self.divide_values(&left_val, &right_val),
188 ">" => self.compare_values(&left_val, &right_val, |a, b| a > b),
190 "<" => self.compare_values(&left_val, &right_val, |a, b| a < b),
191 ">=" => self.compare_values(&left_val, &right_val, |a, b| a >= b),
192 "<=" => self.compare_values(&left_val, &right_val, |a, b| a <= b),
193 "=" => self.compare_values(&left_val, &right_val, |a, b| a == b),
194 "!=" | "<>" => self.compare_values(&left_val, &right_val, |a, b| a != b),
195 _ => Err(anyhow!("Unsupported arithmetic operator: {}", op)),
196 }
197 }
198
199 fn add_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
201 match (left, right) {
202 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a + b)),
203 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 + b)),
204 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a + *b as f64)),
205 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a + b)),
206 _ => Err(anyhow!("Cannot add {:?} and {:?}", left, right)),
207 }
208 }
209
210 fn subtract_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
212 match (left, right) {
213 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a - b)),
214 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 - b)),
215 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a - *b as f64)),
216 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a - b)),
217 _ => Err(anyhow!("Cannot subtract {:?} and {:?}", left, right)),
218 }
219 }
220
221 fn multiply_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
223 match (left, right) {
224 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a * b)),
225 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 * b)),
226 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a * *b as f64)),
227 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a * b)),
228 _ => Err(anyhow!("Cannot multiply {:?} and {:?}", left, right)),
229 }
230 }
231
232 fn divide_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
234 let is_zero = match right {
236 DataValue::Integer(0) => true,
237 DataValue::Float(f) if *f == 0.0 => true, _ => false,
239 };
240
241 if is_zero {
242 return Err(anyhow!("Division by zero"));
243 }
244
245 match (left, right) {
246 (DataValue::Integer(a), DataValue::Integer(b)) => {
247 if a % b == 0 {
249 Ok(DataValue::Integer(a / b))
250 } else {
251 Ok(DataValue::Float(*a as f64 / *b as f64))
252 }
253 }
254 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 / b)),
255 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a / *b as f64)),
256 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a / b)),
257 _ => Err(anyhow!("Cannot divide {:?} and {:?}", left, right)),
258 }
259 }
260
261 fn format_value(&self, value: &DataValue) -> String {
263 match value {
264 DataValue::Integer(i) => i.to_string(),
265 DataValue::Float(f) => f.to_string(),
266 DataValue::String(s) => format!("'{}'", s),
267 _ => format!("{:?}", value),
268 }
269 }
270
271 fn compare_values<F>(&self, left: &DataValue, right: &DataValue, op: F) -> Result<DataValue>
273 where
274 F: Fn(f64, f64) -> bool,
275 {
276 debug!(
277 "ArithmeticEvaluator: comparing values {:?} and {:?}",
278 left, right
279 );
280
281 let result = match (left, right) {
282 (DataValue::Integer(a), DataValue::Integer(b)) => op(*a as f64, *b as f64),
284 (DataValue::Integer(a), DataValue::Float(b)) => op(*a as f64, *b),
285 (DataValue::Float(a), DataValue::Integer(b)) => op(*a, *b as f64),
286 (DataValue::Float(a), DataValue::Float(b)) => op(*a, *b),
287
288 (DataValue::String(a), DataValue::String(b)) => {
290 let a_num = a.parse::<f64>();
291 let b_num = b.parse::<f64>();
292 match (a_num, b_num) {
293 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
296 }
297 (DataValue::InternedString(a), DataValue::InternedString(b)) => {
298 let a_num = a.parse::<f64>();
299 let b_num = b.parse::<f64>();
300 match (a_num, b_num) {
301 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
304 }
305 (DataValue::String(a), DataValue::InternedString(b)) => {
306 let a_num = a.parse::<f64>();
307 let b_num = b.parse::<f64>();
308 match (a_num, b_num) {
309 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
312 }
313 (DataValue::InternedString(a), DataValue::String(b)) => {
314 let a_num = a.parse::<f64>();
315 let b_num = b.parse::<f64>();
316 match (a_num, b_num) {
317 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
320 }
321
322 (DataValue::String(a), DataValue::Integer(b)) => {
324 match a.parse::<f64>() {
325 Ok(a_val) => op(a_val, *b as f64),
326 Err(_) => false, }
328 }
329 (DataValue::Integer(a), DataValue::String(b)) => {
330 match b.parse::<f64>() {
331 Ok(b_val) => op(*a as f64, b_val),
332 Err(_) => false, }
334 }
335 (DataValue::String(a), DataValue::Float(b)) => match a.parse::<f64>() {
336 Ok(a_val) => op(a_val, *b),
337 Err(_) => false,
338 },
339 (DataValue::Float(a), DataValue::String(b)) => match b.parse::<f64>() {
340 Ok(b_val) => op(*a, b_val),
341 Err(_) => false,
342 },
343
344 (DataValue::Null, _) | (_, DataValue::Null) => false,
346
347 (DataValue::Boolean(a), DataValue::Boolean(b)) => {
349 op(if *a { 1.0 } else { 0.0 }, if *b { 1.0 } else { 0.0 })
350 }
351
352 _ => {
353 debug!(
354 "ArithmeticEvaluator: unsupported comparison between {:?} and {:?}",
355 left, right
356 );
357 false
358 }
359 };
360
361 debug!("ArithmeticEvaluator: comparison result: {}", result);
362 Ok(DataValue::Boolean(result))
363 }
364
365 fn evaluate_function(
367 &self,
368 name: &str,
369 args: &[SqlExpression],
370 row_index: usize,
371 ) -> Result<DataValue> {
372 match name.to_uppercase().as_str() {
374 "ROUND" => {
375 if args.is_empty() || args.len() > 2 {
376 return Err(anyhow!("ROUND requires 1 or 2 arguments"));
377 }
378
379 let value = self.evaluate(&args[0], row_index)?;
381
382 let decimals = if args.len() == 2 {
384 match self.evaluate(&args[1], row_index)? {
385 DataValue::Integer(n) => n as i32,
386 DataValue::Float(f) => f as i32,
387 _ => return Err(anyhow!("ROUND precision must be a number")),
388 }
389 } else {
390 0
391 };
392
393 match value {
395 DataValue::Integer(n) => Ok(DataValue::Integer(n)), DataValue::Float(f) => {
397 if decimals >= 0 {
398 let multiplier = 10_f64.powi(decimals);
399 let rounded = (f * multiplier).round() / multiplier;
400 if decimals == 0 {
401 Ok(DataValue::Integer(rounded as i64))
403 } else {
404 Ok(DataValue::Float(rounded))
405 }
406 } else {
407 let divisor = 10_f64.powi(-decimals);
409 let rounded = (f / divisor).round() * divisor;
410 Ok(DataValue::Float(rounded))
411 }
412 }
413 _ => Err(anyhow!("ROUND can only be applied to numeric values")),
414 }
415 }
416 "ABS" => {
417 if args.len() != 1 {
418 return Err(anyhow!("ABS requires exactly 1 argument"));
419 }
420
421 let value = self.evaluate(&args[0], row_index)?;
422 match value {
423 DataValue::Integer(n) => Ok(DataValue::Integer(n.abs())),
424 DataValue::Float(f) => Ok(DataValue::Float(f.abs())),
425 _ => Err(anyhow!("ABS can only be applied to numeric values")),
426 }
427 }
428 "FLOOR" => {
429 if args.len() != 1 {
430 return Err(anyhow!("FLOOR requires exactly 1 argument"));
431 }
432
433 let value = self.evaluate(&args[0], row_index)?;
434 match value {
435 DataValue::Integer(n) => Ok(DataValue::Integer(n)),
436 DataValue::Float(f) => Ok(DataValue::Integer(f.floor() as i64)),
437 _ => Err(anyhow!("FLOOR can only be applied to numeric values")),
438 }
439 }
440 "CEILING" | "CEIL" => {
441 if args.len() != 1 {
442 return Err(anyhow!("CEILING requires exactly 1 argument"));
443 }
444
445 let value = self.evaluate(&args[0], row_index)?;
446 match value {
447 DataValue::Integer(n) => Ok(DataValue::Integer(n)),
448 DataValue::Float(f) => Ok(DataValue::Integer(f.ceil() as i64)),
449 _ => Err(anyhow!("CEILING can only be applied to numeric values")),
450 }
451 }
452 "CONVERT" => {
453 if args.len() != 3 {
454 return Err(anyhow!(
455 "CONVERT requires exactly 3 arguments: value, from_unit, to_unit"
456 ));
457 }
458
459 let value = self.evaluate(&args[0], row_index)?;
461 let numeric_value = match value {
462 DataValue::Integer(n) => n as f64,
463 DataValue::Float(f) => f,
464 _ => return Err(anyhow!("CONVERT first argument must be numeric")),
465 };
466
467 let from_unit = match self.evaluate(&args[1], row_index)? {
469 DataValue::String(s) => s,
470 DataValue::InternedString(s) => s.to_string(),
471 _ => {
472 return Err(anyhow!(
473 "CONVERT second argument must be a string (from_unit)"
474 ))
475 }
476 };
477
478 let to_unit = match self.evaluate(&args[2], row_index)? {
479 DataValue::String(s) => s,
480 DataValue::InternedString(s) => s.to_string(),
481 _ => return Err(anyhow!("CONVERT third argument must be a string (to_unit)")),
482 };
483
484 match crate::data::unit_converter::convert_units(
486 numeric_value,
487 &from_unit,
488 &to_unit,
489 ) {
490 Ok(result) => Ok(DataValue::Float(result)),
491 Err(e) => Err(anyhow!("Unit conversion error: {}", e)),
492 }
493 }
494 "MOD" => {
495 if args.len() != 2 {
496 return Err(anyhow!("MOD requires exactly 2 arguments"));
497 }
498
499 let dividend = self.evaluate(&args[0], row_index)?;
500 let divisor = self.evaluate(&args[1], row_index)?;
501
502 match (÷nd, &divisor) {
503 (DataValue::Integer(n), DataValue::Integer(d)) => {
504 if *d == 0 {
505 return Err(anyhow!("Division by zero in MOD"));
506 }
507 Ok(DataValue::Integer(n % d))
508 }
509 _ => {
510 let n = match dividend {
512 DataValue::Integer(i) => i as f64,
513 DataValue::Float(f) => f,
514 _ => return Err(anyhow!("MOD requires numeric arguments")),
515 };
516 let d = match divisor {
517 DataValue::Integer(i) => i as f64,
518 DataValue::Float(f) => f,
519 _ => return Err(anyhow!("MOD requires numeric arguments")),
520 };
521 if d == 0.0 {
522 return Err(anyhow!("Division by zero in MOD"));
523 }
524 Ok(DataValue::Float(n % d))
525 }
526 }
527 }
528 "QUOTIENT" => {
529 if args.len() != 2 {
530 return Err(anyhow!("QUOTIENT requires exactly 2 arguments"));
531 }
532
533 let numerator = self.evaluate(&args[0], row_index)?;
534 let denominator = self.evaluate(&args[1], row_index)?;
535
536 match (&numerator, &denominator) {
537 (DataValue::Integer(n), DataValue::Integer(d)) => {
538 if *d == 0 {
539 return Err(anyhow!("Division by zero in QUOTIENT"));
540 }
541 Ok(DataValue::Integer(n / d))
542 }
543 _ => {
544 let n = match numerator {
546 DataValue::Integer(i) => i as f64,
547 DataValue::Float(f) => f,
548 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
549 };
550 let d = match denominator {
551 DataValue::Integer(i) => i as f64,
552 DataValue::Float(f) => f,
553 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
554 };
555 if d == 0.0 {
556 return Err(anyhow!("Division by zero in QUOTIENT"));
557 }
558 Ok(DataValue::Integer((n / d).trunc() as i64))
559 }
560 }
561 }
562 "POWER" | "POW" => {
563 if args.len() != 2 {
564 return Err(anyhow!("POWER requires exactly 2 arguments"));
565 }
566
567 let base = self.evaluate(&args[0], row_index)?;
568 let exponent = self.evaluate(&args[1], row_index)?;
569
570 match (&base, &exponent) {
571 (DataValue::Integer(b), DataValue::Integer(e)) => {
572 if *e >= 0 && *e <= i32::MAX as i64 {
573 Ok(DataValue::Float((*b as f64).powi(*e as i32)))
574 } else {
575 Ok(DataValue::Float((*b as f64).powf(*e as f64)))
576 }
577 }
578 _ => {
579 let b = match base {
581 DataValue::Integer(i) => i as f64,
582 DataValue::Float(f) => f,
583 _ => return Err(anyhow!("POWER requires numeric arguments")),
584 };
585 let e = match exponent {
586 DataValue::Integer(i) => i as f64,
587 DataValue::Float(f) => f,
588 _ => return Err(anyhow!("POWER requires numeric arguments")),
589 };
590 Ok(DataValue::Float(b.powf(e)))
591 }
592 }
593 }
594 "SQRT" => {
595 if args.len() != 1 {
596 return Err(anyhow!("SQRT requires exactly 1 argument"));
597 }
598
599 let value = self.evaluate(&args[0], row_index)?;
600 match value {
601 DataValue::Integer(n) => {
602 if n < 0 {
603 return Err(anyhow!("SQRT of negative number"));
604 }
605 Ok(DataValue::Float((n as f64).sqrt()))
606 }
607 DataValue::Float(f) => {
608 if f < 0.0 {
609 return Err(anyhow!("SQRT of negative number"));
610 }
611 Ok(DataValue::Float(f.sqrt()))
612 }
613 _ => Err(anyhow!("SQRT can only be applied to numeric values")),
614 }
615 }
616 "EXP" => {
617 if args.len() != 1 {
618 return Err(anyhow!("EXP requires exactly 1 argument"));
619 }
620
621 let value = self.evaluate(&args[0], row_index)?;
622 match value {
623 DataValue::Integer(n) => Ok(DataValue::Float((n as f64).exp())),
624 DataValue::Float(f) => Ok(DataValue::Float(f.exp())),
625 _ => Err(anyhow!("EXP can only be applied to numeric values")),
626 }
627 }
628 "LN" => {
629 if args.len() != 1 {
630 return Err(anyhow!("LN requires exactly 1 argument"));
631 }
632
633 let value = self.evaluate(&args[0], row_index)?;
634 match value {
635 DataValue::Integer(n) => {
636 if n <= 0 {
637 return Err(anyhow!("LN of non-positive number"));
638 }
639 Ok(DataValue::Float((n as f64).ln()))
640 }
641 DataValue::Float(f) => {
642 if f <= 0.0 {
643 return Err(anyhow!("LN of non-positive number"));
644 }
645 Ok(DataValue::Float(f.ln()))
646 }
647 _ => Err(anyhow!("LN can only be applied to numeric values")),
648 }
649 }
650 "LOG" | "LOG10" => {
651 if name == "LOG" && args.len() == 2 {
652 let value = self.evaluate(&args[0], row_index)?;
654 let base = self.evaluate(&args[1], row_index)?;
655
656 let n = match value {
657 DataValue::Integer(i) => i as f64,
658 DataValue::Float(f) => f,
659 _ => return Err(anyhow!("LOG requires numeric arguments")),
660 };
661 let b = match base {
662 DataValue::Integer(i) => i as f64,
663 DataValue::Float(f) => f,
664 _ => return Err(anyhow!("LOG requires numeric arguments")),
665 };
666
667 if n <= 0.0 {
668 return Err(anyhow!("LOG of non-positive number"));
669 }
670 if b <= 0.0 || b == 1.0 {
671 return Err(anyhow!("Invalid LOG base"));
672 }
673 Ok(DataValue::Float(n.log(b)))
674 } else if (name == "LOG" && args.len() == 1) || name == "LOG10" {
675 if args.len() != 1 {
677 return Err(anyhow!("{} requires exactly 1 argument", name));
678 }
679
680 let value = self.evaluate(&args[0], row_index)?;
681 match value {
682 DataValue::Integer(n) => {
683 if n <= 0 {
684 return Err(anyhow!("LOG10 of non-positive number"));
685 }
686 Ok(DataValue::Float((n as f64).log10()))
687 }
688 DataValue::Float(f) => {
689 if f <= 0.0 {
690 return Err(anyhow!("LOG10 of non-positive number"));
691 }
692 Ok(DataValue::Float(f.log10()))
693 }
694 _ => Err(anyhow!("LOG10 can only be applied to numeric values")),
695 }
696 } else {
697 Err(anyhow!("LOG requires 1 or 2 arguments"))
698 }
699 }
700 "PI" => {
701 if !args.is_empty() {
702 return Err(anyhow!("PI takes no arguments"));
703 }
704 Ok(DataValue::Float(std::f64::consts::PI))
705 }
706 "DATEDIFF" => {
707 if args.len() != 3 {
708 return Err(anyhow!(
709 "DATEDIFF requires exactly 3 arguments: unit, date1, date2"
710 ));
711 }
712
713 let unit = match self.evaluate(&args[0], row_index)? {
715 DataValue::String(s) => s.to_lowercase(),
716 DataValue::InternedString(s) => s.to_lowercase(),
717 _ => return Err(anyhow!("DATEDIFF unit must be a string")),
718 };
719
720 let date_notation = self.date_notation.clone();
722 let parse_datetime = move |value: DataValue| -> Result<DateTime<Utc>> {
723 let parse_string = |s: &str| -> Result<DateTime<Utc>> {
724 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
728 return Ok(Utc.from_utc_datetime(&dt));
729 }
730 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
731 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
732 }
733
734 if date_notation == "european" {
736 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
738 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
739 }
740 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
741 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
742 }
743 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
745 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
746 }
747 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
748 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
749 }
750 } else {
751 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
753 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
754 }
755 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
756 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
757 }
758 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
760 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
761 }
762 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
763 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
764 }
765 }
766
767 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
769 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
770 }
771
772 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
774 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
775 }
776 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
777 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
778 }
779
780 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
782 return Ok(Utc.from_utc_datetime(&dt));
783 }
784 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
785 return Ok(Utc.from_utc_datetime(&dt));
786 }
787
788 if let Ok(dt) = s.parse::<DateTime<Utc>>() {
790 return Ok(dt);
791 }
792
793 Err(anyhow!("Could not parse date: {}. Supported formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MMM-YYYY", s))
794 };
795
796 match value {
797 DataValue::String(s) | DataValue::DateTime(s) => parse_string(&s),
798 DataValue::InternedString(s) => parse_string(s.as_str()),
799 _ => Err(anyhow!("DATEDIFF requires date/datetime values")),
800 }
801 };
802
803 let date1 = parse_datetime(self.evaluate(&args[1], row_index)?)?;
805 let date2 = parse_datetime(self.evaluate(&args[2], row_index)?)?;
806
807 let diff = match unit.as_str() {
809 "day" | "days" => {
810 let duration = date2.signed_duration_since(date1);
811 duration.num_days()
812 }
813 "month" | "months" => {
814 let duration = date2.signed_duration_since(date1);
816 duration.num_days() / 30
817 }
818 "year" | "years" => {
819 let duration = date2.signed_duration_since(date1);
821 duration.num_days() / 365
822 }
823 "hour" | "hours" => {
824 let duration = date2.signed_duration_since(date1);
825 duration.num_hours()
826 }
827 "minute" | "minutes" => {
828 let duration = date2.signed_duration_since(date1);
829 duration.num_minutes()
830 }
831 "second" | "seconds" => {
832 let duration = date2.signed_duration_since(date1);
833 duration.num_seconds()
834 }
835 _ => {
836 return Err(anyhow!(
837 "Unknown DATEDIFF unit: {}. Use: day, month, year, hour, minute, second",
838 unit
839 ))
840 }
841 };
842
843 Ok(DataValue::Integer(diff))
844 }
845 "NOW" => {
846 if !args.is_empty() {
847 return Err(anyhow!("NOW takes no arguments"));
848 }
849 let now = Utc::now();
850 Ok(DataValue::DateTime(
851 now.format("%Y-%m-%d %H:%M:%S").to_string(),
852 ))
853 }
854 "TODAY" => {
855 if !args.is_empty() {
856 return Err(anyhow!("TODAY takes no arguments"));
857 }
858 let today = Utc::now().date_naive();
859 Ok(DataValue::String(today.format("%Y-%m-%d").to_string()))
860 }
861 "DATEADD" => {
862 if args.len() != 3 {
863 return Err(anyhow!(
864 "DATEADD requires exactly 3 arguments: unit, number, date"
865 ));
866 }
867
868 let unit = match self.evaluate(&args[0], row_index)? {
870 DataValue::String(s) => s.to_lowercase(),
871 DataValue::InternedString(s) => s.to_lowercase(),
872 _ => return Err(anyhow!("DATEADD unit must be a string")),
873 };
874
875 let amount = match self.evaluate(&args[1], row_index)? {
877 DataValue::Integer(i) => i,
878 DataValue::Float(f) => f as i64,
879 _ => return Err(anyhow!("DATEADD amount must be a number")),
880 };
881
882 let base_date_value = self.evaluate(&args[2], row_index)?;
884
885 let date_notation = self.date_notation.clone();
887 let parse_datetime = move |value: DataValue| -> Result<DateTime<Utc>> {
888 let parse_string = |s: &str| -> Result<DateTime<Utc>> {
889 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
893 return Ok(Utc.from_utc_datetime(&dt));
894 }
895 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
896 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
897 }
898
899 if date_notation == "european" {
901 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
903 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
904 }
905 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
906 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
907 }
908 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
910 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
911 }
912 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
913 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
914 }
915 } else {
916 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
918 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
919 }
920 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
921 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
922 }
923 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
925 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
926 }
927 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
928 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
929 }
930 }
931
932 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
934 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
935 }
936
937 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
939 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
940 }
941 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
942 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
943 }
944
945 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
947 return Ok(Utc.from_utc_datetime(&dt));
948 }
949 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
950 return Ok(Utc.from_utc_datetime(&dt));
951 }
952
953 if let Ok(dt) = s.parse::<DateTime<Utc>>() {
955 return Ok(dt);
956 }
957
958 Err(anyhow!("Could not parse date: {}. Supported formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MMM-YYYY", s))
959 };
960
961 match value {
962 DataValue::String(s) | DataValue::DateTime(s) => parse_string(&s),
963 DataValue::InternedString(s) => parse_string(s.as_str()),
964 _ => Err(anyhow!("DATEADD requires date/datetime values")),
965 }
966 };
967
968 let base_date = parse_datetime(base_date_value)?;
970
971 let result_date = match unit.as_str() {
973 "day" | "days" => base_date + chrono::Duration::days(amount),
974 "month" | "months" => {
975 let mut year = base_date.year();
977 let mut month = base_date.month() as i32;
978 let day = base_date.day();
979
980 month += amount as i32;
981
982 while month > 12 {
984 month -= 12;
985 year += 1;
986 }
987 while month < 1 {
988 month += 12;
989 year -= 1;
990 }
991
992 let target_date = NaiveDate::from_ymd_opt(year, month as u32, day)
994 .unwrap_or_else(|| {
995 for test_day in (1..=day).rev() {
998 if let Some(date) =
999 NaiveDate::from_ymd_opt(year, month as u32, test_day)
1000 {
1001 return date;
1002 }
1003 }
1004 NaiveDate::from_ymd_opt(year, month as u32, 28).unwrap()
1006 });
1007
1008 Utc.from_utc_datetime(&target_date.and_time(base_date.time()))
1009 }
1010 "year" | "years" => {
1011 let new_year = base_date.year() + amount as i32;
1012 let target_date =
1013 NaiveDate::from_ymd_opt(new_year, base_date.month(), base_date.day())
1014 .unwrap_or_else(|| {
1015 NaiveDate::from_ymd_opt(new_year, base_date.month(), 28)
1017 .unwrap()
1018 });
1019 Utc.from_utc_datetime(&target_date.and_time(base_date.time()))
1020 }
1021 "hour" | "hours" => base_date + chrono::Duration::hours(amount),
1022 "minute" | "minutes" => base_date + chrono::Duration::minutes(amount),
1023 "second" | "seconds" => base_date + chrono::Duration::seconds(amount),
1024 _ => {
1025 return Err(anyhow!(
1026 "Unknown DATEADD unit: {}. Use: day, month, year, hour, minute, second",
1027 unit
1028 ))
1029 }
1030 };
1031
1032 Ok(DataValue::DateTime(
1034 result_date.format("%Y-%m-%d %H:%M:%S").to_string(),
1035 ))
1036 }
1037 "TEXTJOIN" => {
1038 if args.len() < 3 {
1039 return Err(anyhow!("TEXTJOIN requires at least 3 arguments: delimiter, ignore_empty, text1, [text2, ...]"));
1040 }
1041
1042 let delimiter = match self.evaluate(&args[0], row_index)? {
1044 DataValue::String(s) => s,
1045 DataValue::InternedString(s) => s.to_string(),
1046 DataValue::Integer(n) => n.to_string(),
1047 DataValue::Float(f) => f.to_string(),
1048 DataValue::Boolean(b) => b.to_string(),
1049 DataValue::Null => String::new(),
1050 _ => String::new(),
1051 };
1052
1053 let ignore_empty = match self.evaluate(&args[1], row_index)? {
1055 DataValue::Integer(n) => n != 0,
1056 DataValue::Float(f) => f != 0.0,
1057 DataValue::Boolean(b) => b,
1058 DataValue::String(s) => {
1059 !s.is_empty() && s != "0" && s.to_lowercase() != "false"
1060 }
1061 DataValue::InternedString(s) => {
1062 !s.is_empty() && s.as_str() != "0" && s.to_lowercase() != "false"
1063 }
1064 DataValue::Null => false,
1065 _ => true,
1066 };
1067
1068 let mut values = Vec::new();
1070 for i in 2..args.len() {
1071 let value = self.evaluate(&args[i], row_index)?;
1072 let string_value = match value {
1073 DataValue::String(s) => Some(s),
1074 DataValue::InternedString(s) => Some(s.to_string()),
1075 DataValue::Integer(n) => Some(n.to_string()),
1076 DataValue::Float(f) => Some(f.to_string()),
1077 DataValue::Boolean(b) => Some(b.to_string()),
1078 DataValue::DateTime(dt) => Some(dt),
1079 DataValue::Null => {
1080 if ignore_empty {
1081 None
1082 } else {
1083 Some(String::new())
1084 }
1085 }
1086 _ => {
1087 if ignore_empty {
1088 None
1089 } else {
1090 Some(String::new())
1091 }
1092 }
1093 };
1094
1095 if let Some(s) = string_value {
1096 if !ignore_empty || !s.is_empty() {
1097 values.push(s);
1098 }
1099 }
1100 }
1101
1102 Ok(DataValue::String(values.join(&delimiter)))
1103 }
1104 "PI" => {
1105 if !args.is_empty() {
1107 return Err(anyhow!("PI() takes no arguments"));
1108 }
1109 Ok(DataValue::Float(std::f64::consts::PI))
1110 }
1111 "EULER" => {
1112 if !args.is_empty() {
1114 return Err(anyhow!("EULER() takes no arguments"));
1115 }
1116 Ok(DataValue::Float(std::f64::consts::E))
1117 }
1118 "TAU" => {
1119 if !args.is_empty() {
1121 return Err(anyhow!("TAU() takes no arguments"));
1122 }
1123 Ok(DataValue::Float(std::f64::consts::TAU))
1124 }
1125 "PHI" => {
1126 if !args.is_empty() {
1128 return Err(anyhow!("PHI() takes no arguments"));
1129 }
1130 Ok(DataValue::Float(1.618033988749895))
1131 }
1132 "SQRT2" => {
1133 if !args.is_empty() {
1135 return Err(anyhow!("SQRT2() takes no arguments"));
1136 }
1137 Ok(DataValue::Float(std::f64::consts::SQRT_2))
1138 }
1139 "LN2" => {
1140 if !args.is_empty() {
1142 return Err(anyhow!("LN2() takes no arguments"));
1143 }
1144 Ok(DataValue::Float(std::f64::consts::LN_2))
1145 }
1146 "LN10" => {
1147 if !args.is_empty() {
1149 return Err(anyhow!("LN10() takes no arguments"));
1150 }
1151 Ok(DataValue::Float(std::f64::consts::LN_10))
1152 }
1153 "C" | "SPEED_OF_LIGHT" => {
1155 if !args.is_empty() {
1157 return Err(anyhow!("C() takes no arguments"));
1158 }
1159 Ok(DataValue::Float(299792458.0))
1160 }
1161 "G" | "GRAVITATIONAL_CONSTANT" => {
1162 if !args.is_empty() {
1164 return Err(anyhow!("G() takes no arguments"));
1165 }
1166 Ok(DataValue::Float(6.67430e-11))
1167 }
1168 "H" | "PLANCK" => {
1169 if !args.is_empty() {
1171 return Err(anyhow!("PLANCK() takes no arguments"));
1172 }
1173 Ok(DataValue::Float(6.62607015e-34))
1174 }
1175 "HBAR" => {
1176 if !args.is_empty() {
1178 return Err(anyhow!("HBAR() takes no arguments"));
1179 }
1180 Ok(DataValue::Float(1.054571817e-34))
1181 }
1182 "K" | "BOLTZMANN" => {
1183 if !args.is_empty() {
1185 return Err(anyhow!("BOLTZMANN() takes no arguments"));
1186 }
1187 Ok(DataValue::Float(1.380649e-23))
1188 }
1189 "NA" | "AVOGADRO" => {
1190 if !args.is_empty() {
1192 return Err(anyhow!("AVOGADRO() takes no arguments"));
1193 }
1194 Ok(DataValue::Float(6.02214076e23))
1195 }
1196 "R" | "GAS_CONSTANT" => {
1197 if !args.is_empty() {
1199 return Err(anyhow!("R() takes no arguments"));
1200 }
1201 Ok(DataValue::Float(8.314462618))
1202 }
1203 "E0" | "EPSILON0" | "PERMITTIVITY" => {
1205 if !args.is_empty() {
1207 return Err(anyhow!("E0() takes no arguments"));
1208 }
1209 Ok(DataValue::Float(8.8541878128e-12))
1210 }
1211 "MU0" | "PERMEABILITY" => {
1212 if !args.is_empty() {
1214 return Err(anyhow!("MU0() takes no arguments"));
1215 }
1216 Ok(DataValue::Float(1.25663706212e-6))
1217 }
1218 "QE" | "ELEMENTARY_CHARGE" => {
1219 if !args.is_empty() {
1221 return Err(anyhow!("QE() takes no arguments"));
1222 }
1223 Ok(DataValue::Float(1.602176634e-19))
1224 }
1225 "ME" | "MASS_ELECTRON" => {
1227 if !args.is_empty() {
1229 return Err(anyhow!("ME() takes no arguments"));
1230 }
1231 Ok(DataValue::Float(9.1093837015e-31))
1232 }
1233 "MP" | "MASS_PROTON" => {
1234 if !args.is_empty() {
1236 return Err(anyhow!("MP() takes no arguments"));
1237 }
1238 Ok(DataValue::Float(1.67262192369e-27))
1239 }
1240 "MN" | "MASS_NEUTRON" => {
1241 if !args.is_empty() {
1243 return Err(anyhow!("MN() takes no arguments"));
1244 }
1245 Ok(DataValue::Float(1.67492749804e-27))
1246 }
1247 "AMU" | "ATOMIC_MASS_UNIT" => {
1248 if !args.is_empty() {
1250 return Err(anyhow!("AMU() takes no arguments"));
1251 }
1252 Ok(DataValue::Float(1.66053906660e-27))
1253 }
1254 "ALPHA" | "FINE_STRUCTURE" => {
1256 if !args.is_empty() {
1258 return Err(anyhow!("ALPHA() takes no arguments"));
1259 }
1260 Ok(DataValue::Float(7.2973525693e-3))
1261 }
1262 "RY" | "RYDBERG" => {
1263 if !args.is_empty() {
1265 return Err(anyhow!("RYDBERG() takes no arguments"));
1266 }
1267 Ok(DataValue::Float(10973731.568160))
1268 }
1269 "SIGMA" | "STEFAN_BOLTZMANN" => {
1270 if !args.is_empty() {
1272 return Err(anyhow!("SIGMA() takes no arguments"));
1273 }
1274 Ok(DataValue::Float(5.670374419e-8))
1275 }
1276 "RE" | "RADIUS_ELECTRON" => {
1278 if !args.is_empty() {
1280 return Err(anyhow!("RE() takes no arguments"));
1281 }
1282 Ok(DataValue::Float(2.8179403262e-15))
1283 }
1284 "RP" | "RADIUS_PROTON" => {
1285 if !args.is_empty() {
1287 return Err(anyhow!("RP() takes no arguments"));
1288 }
1289 Ok(DataValue::Float(8.414e-16))
1290 }
1291 "RN" | "RADIUS_NEUTRON" => {
1292 if !args.is_empty() {
1294 return Err(anyhow!("RN() takes no arguments"));
1295 }
1296 Ok(DataValue::Float(8.4e-16))
1297 }
1298 "MASS_SUN" | "MSUN" => {
1300 if !args.is_empty() {
1302 return Err(anyhow!("MASS_SUN() takes no arguments"));
1303 }
1304 Ok(DataValue::Float(1.98892e30))
1305 }
1306 "RADIUS_SUN" | "RSUN" => {
1307 if !args.is_empty() {
1309 return Err(anyhow!("RADIUS_SUN() takes no arguments"));
1310 }
1311 Ok(DataValue::Float(6.96342e8))
1312 }
1313 "MASS_EARTH" | "MEARTH" => {
1314 if !args.is_empty() {
1316 return Err(anyhow!("MASS_EARTH() takes no arguments"));
1317 }
1318 Ok(DataValue::Float(5.97237e24))
1319 }
1320 "RADIUS_EARTH" | "REARTH" => {
1321 if !args.is_empty() {
1323 return Err(anyhow!("RADIUS_EARTH() takes no arguments"));
1324 }
1325 Ok(DataValue::Float(6.371e6))
1326 }
1327 "MASS_MOON" | "MMOON" => {
1328 if !args.is_empty() {
1330 return Err(anyhow!("MASS_MOON() takes no arguments"));
1331 }
1332 Ok(DataValue::Float(7.342e22))
1333 }
1334 "RADIUS_MOON" | "RMOON" => {
1335 if !args.is_empty() {
1337 return Err(anyhow!("RADIUS_MOON() takes no arguments"));
1338 }
1339 Ok(DataValue::Float(1.7374e6))
1340 }
1341 "MASS_MERCURY" => {
1343 if !args.is_empty() {
1345 return Err(anyhow!("MASS_MERCURY() takes no arguments"));
1346 }
1347 Ok(DataValue::Float(3.3011e23))
1348 }
1349 "MASS_VENUS" => {
1350 if !args.is_empty() {
1352 return Err(anyhow!("MASS_VENUS() takes no arguments"));
1353 }
1354 Ok(DataValue::Float(4.8675e24))
1355 }
1356 "MASS_MARS" => {
1357 if !args.is_empty() {
1359 return Err(anyhow!("MASS_MARS() takes no arguments"));
1360 }
1361 Ok(DataValue::Float(6.4171e23))
1362 }
1363 "MASS_JUPITER" => {
1364 if !args.is_empty() {
1366 return Err(anyhow!("MASS_JUPITER() takes no arguments"));
1367 }
1368 Ok(DataValue::Float(1.8982e27))
1369 }
1370 "MASS_SATURN" => {
1371 if !args.is_empty() {
1373 return Err(anyhow!("MASS_SATURN() takes no arguments"));
1374 }
1375 Ok(DataValue::Float(5.6834e26))
1376 }
1377 "MASS_URANUS" => {
1378 if !args.is_empty() {
1380 return Err(anyhow!("MASS_URANUS() takes no arguments"));
1381 }
1382 Ok(DataValue::Float(8.6810e25))
1383 }
1384 "MASS_NEPTUNE" => {
1385 if !args.is_empty() {
1387 return Err(anyhow!("MASS_NEPTUNE() takes no arguments"));
1388 }
1389 Ok(DataValue::Float(1.02413e26))
1390 }
1391 "DIST_MERCURY" | "AU_MERCURY" => {
1393 if !args.is_empty() {
1395 return Err(anyhow!("DIST_MERCURY() takes no arguments"));
1396 }
1397 Ok(DataValue::Float(5.791e10))
1398 }
1399 "DIST_VENUS" | "AU_VENUS" => {
1400 if !args.is_empty() {
1402 return Err(anyhow!("DIST_VENUS() takes no arguments"));
1403 }
1404 Ok(DataValue::Float(1.082e11))
1405 }
1406 "DIST_EARTH" | "AU_EARTH" | "AU" => {
1407 if !args.is_empty() {
1409 return Err(anyhow!("AU() takes no arguments"));
1410 }
1411 Ok(DataValue::Float(1.495978707e11))
1412 }
1413 "DIST_MARS" | "AU_MARS" => {
1414 if !args.is_empty() {
1416 return Err(anyhow!("DIST_MARS() takes no arguments"));
1417 }
1418 Ok(DataValue::Float(2.279e11))
1419 }
1420 "DIST_JUPITER" | "AU_JUPITER" => {
1421 if !args.is_empty() {
1423 return Err(anyhow!("DIST_JUPITER() takes no arguments"));
1424 }
1425 Ok(DataValue::Float(7.786e11))
1426 }
1427 "DIST_SATURN" | "AU_SATURN" => {
1428 if !args.is_empty() {
1430 return Err(anyhow!("DIST_SATURN() takes no arguments"));
1431 }
1432 Ok(DataValue::Float(1.4335e12))
1433 }
1434 "DIST_URANUS" | "AU_URANUS" => {
1435 if !args.is_empty() {
1437 return Err(anyhow!("DIST_URANUS() takes no arguments"));
1438 }
1439 Ok(DataValue::Float(2.8725e12))
1440 }
1441 "DIST_NEPTUNE" | "AU_NEPTUNE" => {
1442 if !args.is_empty() {
1444 return Err(anyhow!("DIST_NEPTUNE() takes no arguments"));
1445 }
1446 Ok(DataValue::Float(4.4951e12))
1447 }
1448 "PARSEC" | "PC" => {
1450 if !args.is_empty() {
1452 return Err(anyhow!("PARSEC() takes no arguments"));
1453 }
1454 Ok(DataValue::Float(3.0857e16))
1455 }
1456 "LIGHTYEAR" | "LY" => {
1457 if !args.is_empty() {
1459 return Err(anyhow!("LIGHTYEAR() takes no arguments"));
1460 }
1461 Ok(DataValue::Float(9.4607e15))
1462 }
1463 "DEGREES" => {
1465 if args.len() != 1 {
1467 return Err(anyhow!("DEGREES requires exactly 1 argument"));
1468 }
1469 let radians = match self.evaluate(&args[0], row_index)? {
1470 DataValue::Integer(n) => n as f64,
1471 DataValue::Float(f) => f,
1472 _ => return Err(anyhow!("DEGREES requires a numeric argument")),
1473 };
1474 Ok(DataValue::Float(radians * 180.0 / std::f64::consts::PI))
1475 }
1476 "RADIANS" => {
1477 if args.len() != 1 {
1479 return Err(anyhow!("RADIANS requires exactly 1 argument"));
1480 }
1481 let degrees = match self.evaluate(&args[0], row_index)? {
1482 DataValue::Integer(n) => n as f64,
1483 DataValue::Float(f) => f,
1484 _ => return Err(anyhow!("RADIANS requires a numeric argument")),
1485 };
1486 Ok(DataValue::Float(degrees * std::f64::consts::PI / 180.0))
1487 }
1488 "MID" => {
1489 if args.len() != 3 {
1491 return Err(anyhow!(
1492 "MID requires exactly 3 arguments: text, start_position, length"
1493 ));
1494 }
1495
1496 let text = match self.evaluate(&args[0], row_index)? {
1497 DataValue::String(s) => s,
1498 DataValue::InternedString(s) => s.to_string(),
1499 DataValue::Integer(n) => n.to_string(),
1500 DataValue::Float(f) => f.to_string(),
1501 DataValue::Null => String::new(),
1502 _ => return Err(anyhow!("MID first argument must be convertible to text")),
1503 };
1504
1505 let start_pos = match self.evaluate(&args[1], row_index)? {
1506 DataValue::Integer(n) => n,
1507 DataValue::Float(f) => f as i64,
1508 _ => return Err(anyhow!("MID start_position must be a number")),
1509 };
1510
1511 let length = match self.evaluate(&args[2], row_index)? {
1512 DataValue::Integer(n) => n,
1513 DataValue::Float(f) => f as i64,
1514 _ => return Err(anyhow!("MID length must be a number")),
1515 };
1516
1517 if start_pos < 1 {
1519 return Err(anyhow!("MID start_position must be >= 1"));
1520 }
1521 if length < 0 {
1522 return Err(anyhow!("MID length must be >= 0"));
1523 }
1524
1525 let start_idx = (start_pos - 1) as usize;
1527 let chars: Vec<char> = text.chars().collect();
1528
1529 if start_idx >= chars.len() {
1531 return Ok(DataValue::String(String::new()));
1532 }
1533
1534 let end_idx = std::cmp::min(start_idx + length as usize, chars.len());
1536 let result: String = chars[start_idx..end_idx].iter().collect();
1537
1538 Ok(DataValue::String(result))
1539 }
1540 "UPPER" => {
1541 if args.len() != 1 {
1542 return Err(anyhow!("UPPER requires exactly 1 argument"));
1543 }
1544
1545 let text = match self.evaluate(&args[0], row_index)? {
1546 DataValue::String(s) => s,
1547 DataValue::InternedString(s) => s.to_string(),
1548 DataValue::Integer(n) => n.to_string(),
1549 DataValue::Float(f) => f.to_string(),
1550 DataValue::Null => String::new(),
1551 _ => return Err(anyhow!("UPPER argument must be convertible to text")),
1552 };
1553
1554 Ok(DataValue::String(text.to_uppercase()))
1555 }
1556 "LOWER" => {
1557 if args.len() != 1 {
1558 return Err(anyhow!("LOWER requires exactly 1 argument"));
1559 }
1560
1561 let text = match self.evaluate(&args[0], row_index)? {
1562 DataValue::String(s) => s,
1563 DataValue::InternedString(s) => s.to_string(),
1564 DataValue::Integer(n) => n.to_string(),
1565 DataValue::Float(f) => f.to_string(),
1566 DataValue::Null => String::new(),
1567 _ => return Err(anyhow!("LOWER argument must be convertible to text")),
1568 };
1569
1570 Ok(DataValue::String(text.to_lowercase()))
1571 }
1572 "TRIM" => {
1573 if args.len() != 1 {
1574 return Err(anyhow!("TRIM requires exactly 1 argument"));
1575 }
1576
1577 let text = match self.evaluate(&args[0], row_index)? {
1578 DataValue::String(s) => s,
1579 DataValue::InternedString(s) => s.to_string(),
1580 DataValue::Integer(n) => n.to_string(),
1581 DataValue::Float(f) => f.to_string(),
1582 DataValue::Null => String::new(),
1583 _ => return Err(anyhow!("TRIM argument must be convertible to text")),
1584 };
1585
1586 Ok(DataValue::String(text.trim().to_string()))
1587 }
1588 _ => Err(anyhow!("Unknown function: {}", name)),
1589 }
1590 }
1591
1592 fn evaluate_method_call(
1594 &self,
1595 object: &str,
1596 method: &str,
1597 args: &[SqlExpression],
1598 row_index: usize,
1599 ) -> Result<DataValue> {
1600 let col_index = self.table.get_column_index(object).ok_or_else(|| {
1602 let suggestion = self.find_similar_column(object);
1603 match suggestion {
1604 Some(similar) => {
1605 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
1606 }
1607 None => anyhow!("Column '{}' not found", object),
1608 }
1609 })?;
1610
1611 let cell_value = self.table.get_value(row_index, col_index).cloned();
1612
1613 self.evaluate_method_on_value(
1614 &cell_value.unwrap_or(DataValue::Null),
1615 method,
1616 args,
1617 row_index,
1618 )
1619 }
1620
1621 fn evaluate_method_on_value(
1623 &self,
1624 value: &DataValue,
1625 method: &str,
1626 args: &[SqlExpression],
1627 row_index: usize,
1628 ) -> Result<DataValue> {
1629 match method.to_lowercase().as_str() {
1630 "trim" | "trimstart" | "trimend" => {
1631 if !args.is_empty() {
1632 return Err(anyhow!("{} takes no arguments", method));
1633 }
1634
1635 let str_val = match value {
1637 DataValue::String(s) => s.clone(),
1638 DataValue::InternedString(s) => s.to_string(),
1639 DataValue::Integer(n) => n.to_string(),
1640 DataValue::Float(f) => f.to_string(),
1641 DataValue::Boolean(b) => b.to_string(),
1642 DataValue::DateTime(dt) => dt.clone(),
1643 DataValue::Null => return Ok(DataValue::Null),
1644 };
1645
1646 let result = match method.to_lowercase().as_str() {
1647 "trim" => str_val.trim().to_string(),
1648 "trimstart" => str_val.trim_start().to_string(),
1649 "trimend" => str_val.trim_end().to_string(),
1650 _ => unreachable!(),
1651 };
1652
1653 Ok(DataValue::String(result))
1654 }
1655 "length" => {
1656 if !args.is_empty() {
1657 return Err(anyhow!("Length takes no arguments"));
1658 }
1659
1660 let len = match value {
1662 DataValue::String(s) => s.len(),
1663 DataValue::InternedString(s) => s.len(),
1664 DataValue::Integer(n) => n.to_string().len(),
1665 DataValue::Float(f) => f.to_string().len(),
1666 DataValue::Boolean(b) => b.to_string().len(),
1667 DataValue::DateTime(dt) => dt.len(),
1668 DataValue::Null => return Ok(DataValue::Integer(0)),
1669 };
1670
1671 Ok(DataValue::Integer(len as i64))
1672 }
1673 "indexof" => {
1674 if args.len() != 1 {
1675 return Err(anyhow!("IndexOf requires exactly 1 argument"));
1676 }
1677
1678 let search_str = match self.evaluate(&args[0], row_index)? {
1680 DataValue::String(s) => s,
1681 DataValue::InternedString(s) => s.to_string(),
1682 DataValue::Integer(n) => n.to_string(),
1683 DataValue::Float(f) => f.to_string(),
1684 _ => return Err(anyhow!("IndexOf argument must be a string")),
1685 };
1686
1687 let str_val = match value {
1689 DataValue::String(s) => s.clone(),
1690 DataValue::InternedString(s) => s.to_string(),
1691 DataValue::Integer(n) => n.to_string(),
1692 DataValue::Float(f) => f.to_string(),
1693 DataValue::Boolean(b) => b.to_string(),
1694 DataValue::DateTime(dt) => dt.clone(),
1695 DataValue::Null => return Ok(DataValue::Integer(-1)),
1696 };
1697
1698 let index = str_val.find(&search_str).map(|i| i as i64).unwrap_or(-1);
1699
1700 Ok(DataValue::Integer(index))
1701 }
1702 "contains" => {
1703 if args.len() != 1 {
1704 return Err(anyhow!("Contains requires exactly 1 argument"));
1705 }
1706
1707 let search_str = match self.evaluate(&args[0], row_index)? {
1709 DataValue::String(s) => s,
1710 DataValue::InternedString(s) => s.to_string(),
1711 DataValue::Integer(n) => n.to_string(),
1712 DataValue::Float(f) => f.to_string(),
1713 _ => return Err(anyhow!("Contains argument must be a string")),
1714 };
1715
1716 let str_val = match value {
1718 DataValue::String(s) => s.clone(),
1719 DataValue::InternedString(s) => s.to_string(),
1720 DataValue::Integer(n) => n.to_string(),
1721 DataValue::Float(f) => f.to_string(),
1722 DataValue::Boolean(b) => b.to_string(),
1723 DataValue::DateTime(dt) => dt.clone(),
1724 DataValue::Null => return Ok(DataValue::Boolean(false)),
1725 };
1726
1727 let result = str_val.to_lowercase().contains(&search_str.to_lowercase());
1729 Ok(DataValue::Boolean(result))
1730 }
1731 "startswith" => {
1732 if args.len() != 1 {
1733 return Err(anyhow!("StartsWith requires exactly 1 argument"));
1734 }
1735
1736 let prefix = match self.evaluate(&args[0], row_index)? {
1738 DataValue::String(s) => s,
1739 DataValue::InternedString(s) => s.to_string(),
1740 DataValue::Integer(n) => n.to_string(),
1741 DataValue::Float(f) => f.to_string(),
1742 _ => return Err(anyhow!("StartsWith argument must be a string")),
1743 };
1744
1745 let str_val = match value {
1747 DataValue::String(s) => s.clone(),
1748 DataValue::InternedString(s) => s.to_string(),
1749 DataValue::Integer(n) => n.to_string(),
1750 DataValue::Float(f) => f.to_string(),
1751 DataValue::Boolean(b) => b.to_string(),
1752 DataValue::DateTime(dt) => dt.clone(),
1753 DataValue::Null => return Ok(DataValue::Boolean(false)),
1754 };
1755
1756 let result = str_val.to_lowercase().starts_with(&prefix.to_lowercase());
1758 Ok(DataValue::Boolean(result))
1759 }
1760 "endswith" => {
1761 if args.len() != 1 {
1762 return Err(anyhow!("EndsWith requires exactly 1 argument"));
1763 }
1764
1765 let suffix = match self.evaluate(&args[0], row_index)? {
1767 DataValue::String(s) => s,
1768 DataValue::InternedString(s) => s.to_string(),
1769 DataValue::Integer(n) => n.to_string(),
1770 DataValue::Float(f) => f.to_string(),
1771 _ => return Err(anyhow!("EndsWith argument must be a string")),
1772 };
1773
1774 let str_val = match value {
1776 DataValue::String(s) => s.clone(),
1777 DataValue::InternedString(s) => s.to_string(),
1778 DataValue::Integer(n) => n.to_string(),
1779 DataValue::Float(f) => f.to_string(),
1780 DataValue::Boolean(b) => b.to_string(),
1781 DataValue::DateTime(dt) => dt.clone(),
1782 DataValue::Null => return Ok(DataValue::Boolean(false)),
1783 };
1784
1785 let result = str_val.to_lowercase().ends_with(&suffix.to_lowercase());
1787 Ok(DataValue::Boolean(result))
1788 }
1789 _ => Err(anyhow!("Unsupported method: {}", method)),
1790 }
1791 }
1792
1793 fn evaluate_case_expression(
1795 &self,
1796 when_branches: &[crate::sql::recursive_parser::WhenBranch],
1797 else_branch: &Option<Box<SqlExpression>>,
1798 row_index: usize,
1799 ) -> Result<DataValue> {
1800 debug!(
1801 "ArithmeticEvaluator: evaluating CASE expression for row {}",
1802 row_index
1803 );
1804
1805 for branch in when_branches {
1807 let condition_result = self.evaluate_condition_as_bool(&branch.condition, row_index)?;
1809
1810 if condition_result {
1811 debug!("CASE: WHEN condition matched, evaluating result expression");
1812 return self.evaluate(&branch.result, row_index);
1813 }
1814 }
1815
1816 match else_branch {
1818 Some(else_expr) => {
1819 debug!("CASE: No WHEN matched, evaluating ELSE expression");
1820 self.evaluate(else_expr, row_index)
1821 }
1822 None => {
1823 debug!("CASE: No WHEN matched and no ELSE, returning NULL");
1824 Ok(DataValue::Null)
1825 }
1826 }
1827 }
1828
1829 fn evaluate_condition_as_bool(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
1831 let value = self.evaluate(expr, row_index)?;
1832
1833 match value {
1834 DataValue::Boolean(b) => Ok(b),
1835 DataValue::Integer(i) => Ok(i != 0),
1836 DataValue::Float(f) => Ok(f != 0.0),
1837 DataValue::Null => Ok(false),
1838 DataValue::String(s) => Ok(!s.is_empty()),
1839 DataValue::InternedString(s) => Ok(!s.is_empty()),
1840 _ => Ok(true), }
1842 }
1843}
1844
1845#[cfg(test)]
1846mod tests {
1847 use super::*;
1848 use crate::data::datatable::{DataColumn, DataRow};
1849
1850 fn create_test_table() -> DataTable {
1851 let mut table = DataTable::new("test");
1852 table.add_column(DataColumn::new("a"));
1853 table.add_column(DataColumn::new("b"));
1854 table.add_column(DataColumn::new("c"));
1855
1856 table
1857 .add_row(DataRow::new(vec![
1858 DataValue::Integer(10),
1859 DataValue::Float(2.5),
1860 DataValue::Integer(4),
1861 ]))
1862 .unwrap();
1863
1864 table
1865 }
1866
1867 #[test]
1868 fn test_evaluate_column() {
1869 let table = create_test_table();
1870 let evaluator = ArithmeticEvaluator::new(&table);
1871
1872 let expr = SqlExpression::Column("a".to_string());
1873 let result = evaluator.evaluate(&expr, 0).unwrap();
1874 assert_eq!(result, DataValue::Integer(10));
1875 }
1876
1877 #[test]
1878 fn test_evaluate_number_literal() {
1879 let table = create_test_table();
1880 let evaluator = ArithmeticEvaluator::new(&table);
1881
1882 let expr = SqlExpression::NumberLiteral("42".to_string());
1883 let result = evaluator.evaluate(&expr, 0).unwrap();
1884 assert_eq!(result, DataValue::Integer(42));
1885
1886 let expr = SqlExpression::NumberLiteral("3.14".to_string());
1887 let result = evaluator.evaluate(&expr, 0).unwrap();
1888 assert_eq!(result, DataValue::Float(3.14));
1889 }
1890
1891 #[test]
1892 fn test_add_values() {
1893 let table = create_test_table();
1894 let evaluator = ArithmeticEvaluator::new(&table);
1895
1896 let result = evaluator
1898 .add_values(&DataValue::Integer(5), &DataValue::Integer(3))
1899 .unwrap();
1900 assert_eq!(result, DataValue::Integer(8));
1901
1902 let result = evaluator
1904 .add_values(&DataValue::Integer(5), &DataValue::Float(2.5))
1905 .unwrap();
1906 assert_eq!(result, DataValue::Float(7.5));
1907 }
1908
1909 #[test]
1910 fn test_multiply_values() {
1911 let table = create_test_table();
1912 let evaluator = ArithmeticEvaluator::new(&table);
1913
1914 let result = evaluator
1916 .multiply_values(&DataValue::Integer(4), &DataValue::Float(2.5))
1917 .unwrap();
1918 assert_eq!(result, DataValue::Float(10.0));
1919 }
1920
1921 #[test]
1922 fn test_divide_values() {
1923 let table = create_test_table();
1924 let evaluator = ArithmeticEvaluator::new(&table);
1925
1926 let result = evaluator
1928 .divide_values(&DataValue::Integer(10), &DataValue::Integer(2))
1929 .unwrap();
1930 assert_eq!(result, DataValue::Integer(5));
1931
1932 let result = evaluator
1934 .divide_values(&DataValue::Integer(10), &DataValue::Integer(3))
1935 .unwrap();
1936 assert_eq!(result, DataValue::Float(10.0 / 3.0));
1937 }
1938
1939 #[test]
1940 fn test_division_by_zero() {
1941 let table = create_test_table();
1942 let evaluator = ArithmeticEvaluator::new(&table);
1943
1944 let result = evaluator.divide_values(&DataValue::Integer(10), &DataValue::Integer(0));
1945 assert!(result.is_err());
1946 assert!(result.unwrap_err().to_string().contains("Division by zero"));
1947 }
1948
1949 #[test]
1950 fn test_binary_op_expression() {
1951 let table = create_test_table();
1952 let evaluator = ArithmeticEvaluator::new(&table);
1953
1954 let expr = SqlExpression::BinaryOp {
1956 left: Box::new(SqlExpression::Column("a".to_string())),
1957 op: "*".to_string(),
1958 right: Box::new(SqlExpression::Column("b".to_string())),
1959 };
1960
1961 let result = evaluator.evaluate(&expr, 0).unwrap();
1962 assert_eq!(result, DataValue::Float(25.0));
1963 }
1964}