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}
12
13impl<'a> ArithmeticEvaluator<'a> {
14 pub fn new(table: &'a DataTable) -> Self {
15 Self { table }
16 }
17
18 fn find_similar_column(&self, name: &str) -> Option<String> {
20 let columns = self.table.column_names();
21 let mut best_match: Option<(String, usize)> = None;
22
23 for col in columns {
24 let distance = self.edit_distance(&col.to_lowercase(), &name.to_lowercase());
25 let max_distance = if name.len() > 10 { 3 } else { 2 };
28 if distance <= max_distance {
29 match &best_match {
30 None => best_match = Some((col, distance)),
31 Some((_, best_dist)) if distance < *best_dist => {
32 best_match = Some((col, distance));
33 }
34 _ => {}
35 }
36 }
37 }
38
39 best_match.map(|(name, _)| name)
40 }
41
42 fn edit_distance(&self, s1: &str, s2: &str) -> usize {
44 let len1 = s1.len();
45 let len2 = s2.len();
46 let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];
47
48 for i in 0..=len1 {
49 matrix[i][0] = i;
50 }
51 for j in 0..=len2 {
52 matrix[0][j] = j;
53 }
54
55 for (i, c1) in s1.chars().enumerate() {
56 for (j, c2) in s2.chars().enumerate() {
57 let cost = if c1 == c2 { 0 } else { 1 };
58 matrix[i + 1][j + 1] = std::cmp::min(
59 matrix[i][j + 1] + 1, std::cmp::min(
61 matrix[i + 1][j] + 1, matrix[i][j] + cost, ),
64 );
65 }
66 }
67
68 matrix[len1][len2]
69 }
70
71 pub fn evaluate(&self, expr: &SqlExpression, row_index: usize) -> Result<DataValue> {
73 debug!(
74 "ArithmeticEvaluator: evaluating {:?} for row {}",
75 expr, row_index
76 );
77
78 match expr {
79 SqlExpression::Column(column_name) => self.evaluate_column(column_name, row_index),
80 SqlExpression::StringLiteral(s) => Ok(DataValue::String(s.clone())),
81 SqlExpression::NumberLiteral(n) => self.evaluate_number_literal(n),
82 SqlExpression::BinaryOp { left, op, right } => {
83 self.evaluate_binary_op(left, op, right, row_index)
84 }
85 SqlExpression::FunctionCall { name, args } => {
86 self.evaluate_function(name, args, row_index)
87 }
88 SqlExpression::MethodCall {
89 object,
90 method,
91 args,
92 } => self.evaluate_method_call(object, method, args, row_index),
93 SqlExpression::ChainedMethodCall { base, method, args } => {
94 let base_value = self.evaluate(base, row_index)?;
96 self.evaluate_method_on_value(&base_value, method, args, row_index)
97 }
98 SqlExpression::CaseExpression {
99 when_branches,
100 else_branch,
101 } => self.evaluate_case_expression(when_branches, else_branch, row_index),
102 _ => Err(anyhow!(
103 "Unsupported expression type for arithmetic evaluation: {:?}",
104 expr
105 )),
106 }
107 }
108
109 fn evaluate_column(&self, column_name: &str, row_index: usize) -> Result<DataValue> {
111 let col_index = self.table.get_column_index(column_name).ok_or_else(|| {
112 let suggestion = self.find_similar_column(column_name);
113 match suggestion {
114 Some(similar) => anyhow!(
115 "Column '{}' not found. Did you mean '{}'?",
116 column_name,
117 similar
118 ),
119 None => anyhow!("Column '{}' not found", column_name),
120 }
121 })?;
122
123 if row_index >= self.table.row_count() {
124 return Err(anyhow!("Row index {} out of bounds", row_index));
125 }
126
127 let row = self
128 .table
129 .get_row(row_index)
130 .ok_or_else(|| anyhow!("Row {} not found", row_index))?;
131
132 let value = row
133 .get(col_index)
134 .ok_or_else(|| anyhow!("Column index {} out of bounds for row", col_index))?;
135
136 Ok(value.clone())
137 }
138
139 fn evaluate_number_literal(&self, number_str: &str) -> Result<DataValue> {
141 if let Ok(int_val) = number_str.parse::<i64>() {
143 return Ok(DataValue::Integer(int_val));
144 }
145
146 if let Ok(float_val) = number_str.parse::<f64>() {
148 return Ok(DataValue::Float(float_val));
149 }
150
151 Err(anyhow!("Invalid number literal: {}", number_str))
152 }
153
154 fn evaluate_binary_op(
156 &self,
157 left: &SqlExpression,
158 op: &str,
159 right: &SqlExpression,
160 row_index: usize,
161 ) -> Result<DataValue> {
162 let left_val = self.evaluate(left, row_index)?;
163 let right_val = self.evaluate(right, row_index)?;
164
165 debug!(
166 "ArithmeticEvaluator: {} {} {}",
167 self.format_value(&left_val),
168 op,
169 self.format_value(&right_val)
170 );
171
172 match op {
173 "+" => self.add_values(&left_val, &right_val),
174 "-" => self.subtract_values(&left_val, &right_val),
175 "*" => self.multiply_values(&left_val, &right_val),
176 "/" => self.divide_values(&left_val, &right_val),
177 ">" => self.compare_values(&left_val, &right_val, |a, b| a > b),
179 "<" => self.compare_values(&left_val, &right_val, |a, b| a < b),
180 ">=" => self.compare_values(&left_val, &right_val, |a, b| a >= b),
181 "<=" => self.compare_values(&left_val, &right_val, |a, b| a <= b),
182 "=" => self.compare_values(&left_val, &right_val, |a, b| a == b),
183 "!=" | "<>" => self.compare_values(&left_val, &right_val, |a, b| a != b),
184 _ => Err(anyhow!("Unsupported arithmetic operator: {}", op)),
185 }
186 }
187
188 fn add_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
190 match (left, right) {
191 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a + b)),
192 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 + b)),
193 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a + *b as f64)),
194 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a + b)),
195 _ => Err(anyhow!("Cannot add {:?} and {:?}", left, right)),
196 }
197 }
198
199 fn subtract_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 subtract {:?} and {:?}", left, right)),
207 }
208 }
209
210 fn multiply_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 multiply {:?} and {:?}", left, right)),
218 }
219 }
220
221 fn divide_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
223 let is_zero = match right {
225 DataValue::Integer(0) => true,
226 DataValue::Float(f) if *f == 0.0 => true, _ => false,
228 };
229
230 if is_zero {
231 return Err(anyhow!("Division by zero"));
232 }
233
234 match (left, right) {
235 (DataValue::Integer(a), DataValue::Integer(b)) => {
236 if a % b == 0 {
238 Ok(DataValue::Integer(a / b))
239 } else {
240 Ok(DataValue::Float(*a as f64 / *b as f64))
241 }
242 }
243 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 / b)),
244 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a / *b as f64)),
245 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a / b)),
246 _ => Err(anyhow!("Cannot divide {:?} and {:?}", left, right)),
247 }
248 }
249
250 fn format_value(&self, value: &DataValue) -> String {
252 match value {
253 DataValue::Integer(i) => i.to_string(),
254 DataValue::Float(f) => f.to_string(),
255 DataValue::String(s) => format!("'{}'", s),
256 _ => format!("{:?}", value),
257 }
258 }
259
260 fn compare_values<F>(&self, left: &DataValue, right: &DataValue, op: F) -> Result<DataValue>
262 where
263 F: Fn(f64, f64) -> bool,
264 {
265 debug!(
266 "ArithmeticEvaluator: comparing values {:?} and {:?}",
267 left, right
268 );
269
270 let result = match (left, right) {
271 (DataValue::Integer(a), DataValue::Integer(b)) => op(*a as f64, *b as f64),
273 (DataValue::Integer(a), DataValue::Float(b)) => op(*a as f64, *b),
274 (DataValue::Float(a), DataValue::Integer(b)) => op(*a, *b as f64),
275 (DataValue::Float(a), DataValue::Float(b)) => op(*a, *b),
276
277 (DataValue::String(a), DataValue::String(b)) => {
279 let a_num = a.parse::<f64>();
280 let b_num = b.parse::<f64>();
281 match (a_num, b_num) {
282 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
285 }
286 (DataValue::InternedString(a), DataValue::InternedString(b)) => {
287 let a_num = a.parse::<f64>();
288 let b_num = b.parse::<f64>();
289 match (a_num, b_num) {
290 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
293 }
294 (DataValue::String(a), DataValue::InternedString(b)) => {
295 let a_num = a.parse::<f64>();
296 let b_num = b.parse::<f64>();
297 match (a_num, b_num) {
298 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
301 }
302 (DataValue::InternedString(a), DataValue::String(b)) => {
303 let a_num = a.parse::<f64>();
304 let b_num = b.parse::<f64>();
305 match (a_num, b_num) {
306 (Ok(a_val), Ok(b_val)) => op(a_val, b_val), _ => op(a.len() as f64, b.len() as f64), }
309 }
310
311 (DataValue::String(a), DataValue::Integer(b)) => {
313 match a.parse::<f64>() {
314 Ok(a_val) => op(a_val, *b as f64),
315 Err(_) => false, }
317 }
318 (DataValue::Integer(a), DataValue::String(b)) => {
319 match b.parse::<f64>() {
320 Ok(b_val) => op(*a as f64, b_val),
321 Err(_) => false, }
323 }
324 (DataValue::String(a), DataValue::Float(b)) => match a.parse::<f64>() {
325 Ok(a_val) => op(a_val, *b),
326 Err(_) => false,
327 },
328 (DataValue::Float(a), DataValue::String(b)) => match b.parse::<f64>() {
329 Ok(b_val) => op(*a, b_val),
330 Err(_) => false,
331 },
332
333 (DataValue::Null, _) | (_, DataValue::Null) => false,
335
336 (DataValue::Boolean(a), DataValue::Boolean(b)) => {
338 op(if *a { 1.0 } else { 0.0 }, if *b { 1.0 } else { 0.0 })
339 }
340
341 _ => {
342 debug!(
343 "ArithmeticEvaluator: unsupported comparison between {:?} and {:?}",
344 left, right
345 );
346 false
347 }
348 };
349
350 debug!("ArithmeticEvaluator: comparison result: {}", result);
351 Ok(DataValue::Boolean(result))
352 }
353
354 fn evaluate_function(
356 &self,
357 name: &str,
358 args: &[SqlExpression],
359 row_index: usize,
360 ) -> Result<DataValue> {
361 match name.to_uppercase().as_str() {
363 "ROUND" => {
364 if args.is_empty() || args.len() > 2 {
365 return Err(anyhow!("ROUND requires 1 or 2 arguments"));
366 }
367
368 let value = self.evaluate(&args[0], row_index)?;
370
371 let decimals = if args.len() == 2 {
373 match self.evaluate(&args[1], row_index)? {
374 DataValue::Integer(n) => n as i32,
375 DataValue::Float(f) => f as i32,
376 _ => return Err(anyhow!("ROUND precision must be a number")),
377 }
378 } else {
379 0
380 };
381
382 match value {
384 DataValue::Integer(n) => Ok(DataValue::Integer(n)), DataValue::Float(f) => {
386 if decimals >= 0 {
387 let multiplier = 10_f64.powi(decimals);
388 let rounded = (f * multiplier).round() / multiplier;
389 if decimals == 0 {
390 Ok(DataValue::Integer(rounded as i64))
392 } else {
393 Ok(DataValue::Float(rounded))
394 }
395 } else {
396 let divisor = 10_f64.powi(-decimals);
398 let rounded = (f / divisor).round() * divisor;
399 Ok(DataValue::Float(rounded))
400 }
401 }
402 _ => Err(anyhow!("ROUND can only be applied to numeric values")),
403 }
404 }
405 "ABS" => {
406 if args.len() != 1 {
407 return Err(anyhow!("ABS requires exactly 1 argument"));
408 }
409
410 let value = self.evaluate(&args[0], row_index)?;
411 match value {
412 DataValue::Integer(n) => Ok(DataValue::Integer(n.abs())),
413 DataValue::Float(f) => Ok(DataValue::Float(f.abs())),
414 _ => Err(anyhow!("ABS can only be applied to numeric values")),
415 }
416 }
417 "FLOOR" => {
418 if args.len() != 1 {
419 return Err(anyhow!("FLOOR requires exactly 1 argument"));
420 }
421
422 let value = self.evaluate(&args[0], row_index)?;
423 match value {
424 DataValue::Integer(n) => Ok(DataValue::Integer(n)),
425 DataValue::Float(f) => Ok(DataValue::Integer(f.floor() as i64)),
426 _ => Err(anyhow!("FLOOR can only be applied to numeric values")),
427 }
428 }
429 "CEILING" | "CEIL" => {
430 if args.len() != 1 {
431 return Err(anyhow!("CEILING requires exactly 1 argument"));
432 }
433
434 let value = self.evaluate(&args[0], row_index)?;
435 match value {
436 DataValue::Integer(n) => Ok(DataValue::Integer(n)),
437 DataValue::Float(f) => Ok(DataValue::Integer(f.ceil() as i64)),
438 _ => Err(anyhow!("CEILING can only be applied to numeric values")),
439 }
440 }
441 "MOD" => {
442 if args.len() != 2 {
443 return Err(anyhow!("MOD requires exactly 2 arguments"));
444 }
445
446 let dividend = self.evaluate(&args[0], row_index)?;
447 let divisor = self.evaluate(&args[1], row_index)?;
448
449 match (÷nd, &divisor) {
450 (DataValue::Integer(n), DataValue::Integer(d)) => {
451 if *d == 0 {
452 return Err(anyhow!("Division by zero in MOD"));
453 }
454 Ok(DataValue::Integer(n % d))
455 }
456 _ => {
457 let n = match dividend {
459 DataValue::Integer(i) => i as f64,
460 DataValue::Float(f) => f,
461 _ => return Err(anyhow!("MOD requires numeric arguments")),
462 };
463 let d = match divisor {
464 DataValue::Integer(i) => i as f64,
465 DataValue::Float(f) => f,
466 _ => return Err(anyhow!("MOD requires numeric arguments")),
467 };
468 if d == 0.0 {
469 return Err(anyhow!("Division by zero in MOD"));
470 }
471 Ok(DataValue::Float(n % d))
472 }
473 }
474 }
475 "QUOTIENT" => {
476 if args.len() != 2 {
477 return Err(anyhow!("QUOTIENT requires exactly 2 arguments"));
478 }
479
480 let numerator = self.evaluate(&args[0], row_index)?;
481 let denominator = self.evaluate(&args[1], row_index)?;
482
483 match (&numerator, &denominator) {
484 (DataValue::Integer(n), DataValue::Integer(d)) => {
485 if *d == 0 {
486 return Err(anyhow!("Division by zero in QUOTIENT"));
487 }
488 Ok(DataValue::Integer(n / d))
489 }
490 _ => {
491 let n = match numerator {
493 DataValue::Integer(i) => i as f64,
494 DataValue::Float(f) => f,
495 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
496 };
497 let d = match denominator {
498 DataValue::Integer(i) => i as f64,
499 DataValue::Float(f) => f,
500 _ => return Err(anyhow!("QUOTIENT requires numeric arguments")),
501 };
502 if d == 0.0 {
503 return Err(anyhow!("Division by zero in QUOTIENT"));
504 }
505 Ok(DataValue::Integer((n / d).trunc() as i64))
506 }
507 }
508 }
509 "POWER" | "POW" => {
510 if args.len() != 2 {
511 return Err(anyhow!("POWER requires exactly 2 arguments"));
512 }
513
514 let base = self.evaluate(&args[0], row_index)?;
515 let exponent = self.evaluate(&args[1], row_index)?;
516
517 match (&base, &exponent) {
518 (DataValue::Integer(b), DataValue::Integer(e)) => {
519 if *e >= 0 && *e <= i32::MAX as i64 {
520 Ok(DataValue::Float((*b as f64).powi(*e as i32)))
521 } else {
522 Ok(DataValue::Float((*b as f64).powf(*e as f64)))
523 }
524 }
525 _ => {
526 let b = match base {
528 DataValue::Integer(i) => i as f64,
529 DataValue::Float(f) => f,
530 _ => return Err(anyhow!("POWER requires numeric arguments")),
531 };
532 let e = match exponent {
533 DataValue::Integer(i) => i as f64,
534 DataValue::Float(f) => f,
535 _ => return Err(anyhow!("POWER requires numeric arguments")),
536 };
537 Ok(DataValue::Float(b.powf(e)))
538 }
539 }
540 }
541 "SQRT" => {
542 if args.len() != 1 {
543 return Err(anyhow!("SQRT requires exactly 1 argument"));
544 }
545
546 let value = self.evaluate(&args[0], row_index)?;
547 match value {
548 DataValue::Integer(n) => {
549 if n < 0 {
550 return Err(anyhow!("SQRT of negative number"));
551 }
552 Ok(DataValue::Float((n as f64).sqrt()))
553 }
554 DataValue::Float(f) => {
555 if f < 0.0 {
556 return Err(anyhow!("SQRT of negative number"));
557 }
558 Ok(DataValue::Float(f.sqrt()))
559 }
560 _ => Err(anyhow!("SQRT can only be applied to numeric values")),
561 }
562 }
563 "EXP" => {
564 if args.len() != 1 {
565 return Err(anyhow!("EXP requires exactly 1 argument"));
566 }
567
568 let value = self.evaluate(&args[0], row_index)?;
569 match value {
570 DataValue::Integer(n) => Ok(DataValue::Float((n as f64).exp())),
571 DataValue::Float(f) => Ok(DataValue::Float(f.exp())),
572 _ => Err(anyhow!("EXP can only be applied to numeric values")),
573 }
574 }
575 "LN" => {
576 if args.len() != 1 {
577 return Err(anyhow!("LN requires exactly 1 argument"));
578 }
579
580 let value = self.evaluate(&args[0], row_index)?;
581 match value {
582 DataValue::Integer(n) => {
583 if n <= 0 {
584 return Err(anyhow!("LN of non-positive number"));
585 }
586 Ok(DataValue::Float((n as f64).ln()))
587 }
588 DataValue::Float(f) => {
589 if f <= 0.0 {
590 return Err(anyhow!("LN of non-positive number"));
591 }
592 Ok(DataValue::Float(f.ln()))
593 }
594 _ => Err(anyhow!("LN can only be applied to numeric values")),
595 }
596 }
597 "LOG" | "LOG10" => {
598 if name == "LOG" && args.len() == 2 {
599 let value = self.evaluate(&args[0], row_index)?;
601 let base = self.evaluate(&args[1], row_index)?;
602
603 let n = match value {
604 DataValue::Integer(i) => i as f64,
605 DataValue::Float(f) => f,
606 _ => return Err(anyhow!("LOG requires numeric arguments")),
607 };
608 let b = match base {
609 DataValue::Integer(i) => i as f64,
610 DataValue::Float(f) => f,
611 _ => return Err(anyhow!("LOG requires numeric arguments")),
612 };
613
614 if n <= 0.0 {
615 return Err(anyhow!("LOG of non-positive number"));
616 }
617 if b <= 0.0 || b == 1.0 {
618 return Err(anyhow!("Invalid LOG base"));
619 }
620 Ok(DataValue::Float(n.log(b)))
621 } else if (name == "LOG" && args.len() == 1) || name == "LOG10" {
622 if args.len() != 1 {
624 return Err(anyhow!("{} requires exactly 1 argument", name));
625 }
626
627 let value = self.evaluate(&args[0], row_index)?;
628 match value {
629 DataValue::Integer(n) => {
630 if n <= 0 {
631 return Err(anyhow!("LOG10 of non-positive number"));
632 }
633 Ok(DataValue::Float((n as f64).log10()))
634 }
635 DataValue::Float(f) => {
636 if f <= 0.0 {
637 return Err(anyhow!("LOG10 of non-positive number"));
638 }
639 Ok(DataValue::Float(f.log10()))
640 }
641 _ => Err(anyhow!("LOG10 can only be applied to numeric values")),
642 }
643 } else {
644 Err(anyhow!("LOG requires 1 or 2 arguments"))
645 }
646 }
647 "PI" => {
648 if !args.is_empty() {
649 return Err(anyhow!("PI takes no arguments"));
650 }
651 Ok(DataValue::Float(std::f64::consts::PI))
652 }
653 "DATEDIFF" => {
654 if args.len() != 3 {
655 return Err(anyhow!(
656 "DATEDIFF requires exactly 3 arguments: unit, date1, date2"
657 ));
658 }
659
660 let unit = match self.evaluate(&args[0], row_index)? {
662 DataValue::String(s) => s.to_lowercase(),
663 DataValue::InternedString(s) => s.to_lowercase(),
664 _ => return Err(anyhow!("DATEDIFF unit must be a string")),
665 };
666
667 let parse_datetime = |value: DataValue| -> Result<DateTime<Utc>> {
669 let parse_string = |s: &str| -> Result<DateTime<Utc>> {
670 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
674 return Ok(Utc.from_utc_datetime(&dt));
675 }
676 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
677 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
678 }
679
680 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
682 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
683 }
684 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
685 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
686 }
687
688 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
690 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
691 }
692 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
693 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
694 }
695
696 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
698 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
699 }
700
701 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
703 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
704 }
705 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
706 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
707 }
708
709 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
711 return Ok(Utc.from_utc_datetime(&dt));
712 }
713 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
714 return Ok(Utc.from_utc_datetime(&dt));
715 }
716
717 if let Ok(dt) = s.parse::<DateTime<Utc>>() {
719 return Ok(dt);
720 }
721
722 Err(anyhow!("Could not parse date: {}. Supported formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MMM-YYYY", s))
723 };
724
725 match value {
726 DataValue::String(s) | DataValue::DateTime(s) => parse_string(&s),
727 DataValue::InternedString(s) => parse_string(s.as_str()),
728 _ => Err(anyhow!("DATEDIFF requires date/datetime values")),
729 }
730 };
731
732 let date1 = parse_datetime(self.evaluate(&args[1], row_index)?)?;
734 let date2 = parse_datetime(self.evaluate(&args[2], row_index)?)?;
735
736 let diff = match unit.as_str() {
738 "day" | "days" => {
739 let duration = date2.signed_duration_since(date1);
740 duration.num_days()
741 }
742 "month" | "months" => {
743 let duration = date2.signed_duration_since(date1);
745 duration.num_days() / 30
746 }
747 "year" | "years" => {
748 let duration = date2.signed_duration_since(date1);
750 duration.num_days() / 365
751 }
752 "hour" | "hours" => {
753 let duration = date2.signed_duration_since(date1);
754 duration.num_hours()
755 }
756 "minute" | "minutes" => {
757 let duration = date2.signed_duration_since(date1);
758 duration.num_minutes()
759 }
760 "second" | "seconds" => {
761 let duration = date2.signed_duration_since(date1);
762 duration.num_seconds()
763 }
764 _ => {
765 return Err(anyhow!(
766 "Unknown DATEDIFF unit: {}. Use: day, month, year, hour, minute, second",
767 unit
768 ))
769 }
770 };
771
772 Ok(DataValue::Integer(diff))
773 }
774 "NOW" => {
775 if !args.is_empty() {
776 return Err(anyhow!("NOW takes no arguments"));
777 }
778 let now = Utc::now();
779 Ok(DataValue::DateTime(
780 now.format("%Y-%m-%d %H:%M:%S").to_string(),
781 ))
782 }
783 "TODAY" => {
784 if !args.is_empty() {
785 return Err(anyhow!("TODAY takes no arguments"));
786 }
787 let today = Utc::now().date_naive();
788 Ok(DataValue::String(today.format("%Y-%m-%d").to_string()))
789 }
790 "DATEADD" => {
791 if args.len() != 3 {
792 return Err(anyhow!(
793 "DATEADD requires exactly 3 arguments: unit, number, date"
794 ));
795 }
796
797 let unit = match self.evaluate(&args[0], row_index)? {
799 DataValue::String(s) => s.to_lowercase(),
800 DataValue::InternedString(s) => s.to_lowercase(),
801 _ => return Err(anyhow!("DATEADD unit must be a string")),
802 };
803
804 let amount = match self.evaluate(&args[1], row_index)? {
806 DataValue::Integer(i) => i,
807 DataValue::Float(f) => f as i64,
808 _ => return Err(anyhow!("DATEADD amount must be a number")),
809 };
810
811 let base_date_value = self.evaluate(&args[2], row_index)?;
813
814 let parse_datetime = |value: DataValue| -> Result<DateTime<Utc>> {
816 let parse_string = |s: &str| -> Result<DateTime<Utc>> {
817 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
821 return Ok(Utc.from_utc_datetime(&dt));
822 }
823 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
824 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
825 }
826
827 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
829 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
830 }
831 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
832 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
833 }
834
835 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
837 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
838 }
839 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
840 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
841 }
842
843 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
845 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
846 }
847
848 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
850 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
851 }
852 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
853 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
854 }
855
856 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
858 return Ok(Utc.from_utc_datetime(&dt));
859 }
860 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
861 return Ok(Utc.from_utc_datetime(&dt));
862 }
863
864 if let Ok(dt) = s.parse::<DateTime<Utc>>() {
866 return Ok(dt);
867 }
868
869 Err(anyhow!("Could not parse date: {}. Supported formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MMM-YYYY", s))
870 };
871
872 match value {
873 DataValue::String(s) | DataValue::DateTime(s) => parse_string(&s),
874 DataValue::InternedString(s) => parse_string(s.as_str()),
875 _ => Err(anyhow!("DATEADD requires date/datetime values")),
876 }
877 };
878
879 let base_date = parse_datetime(base_date_value)?;
881
882 let result_date = match unit.as_str() {
884 "day" | "days" => base_date + chrono::Duration::days(amount),
885 "month" | "months" => {
886 let mut year = base_date.year();
888 let mut month = base_date.month() as i32;
889 let day = base_date.day();
890
891 month += amount as i32;
892
893 while month > 12 {
895 month -= 12;
896 year += 1;
897 }
898 while month < 1 {
899 month += 12;
900 year -= 1;
901 }
902
903 let target_date = NaiveDate::from_ymd_opt(year, month as u32, day)
905 .unwrap_or_else(|| {
906 for test_day in (1..=day).rev() {
909 if let Some(date) =
910 NaiveDate::from_ymd_opt(year, month as u32, test_day)
911 {
912 return date;
913 }
914 }
915 NaiveDate::from_ymd_opt(year, month as u32, 28).unwrap()
917 });
918
919 Utc.from_utc_datetime(&target_date.and_time(base_date.time()))
920 }
921 "year" | "years" => {
922 let new_year = base_date.year() + amount as i32;
923 let target_date =
924 NaiveDate::from_ymd_opt(new_year, base_date.month(), base_date.day())
925 .unwrap_or_else(|| {
926 NaiveDate::from_ymd_opt(new_year, base_date.month(), 28)
928 .unwrap()
929 });
930 Utc.from_utc_datetime(&target_date.and_time(base_date.time()))
931 }
932 "hour" | "hours" => base_date + chrono::Duration::hours(amount),
933 "minute" | "minutes" => base_date + chrono::Duration::minutes(amount),
934 "second" | "seconds" => base_date + chrono::Duration::seconds(amount),
935 _ => {
936 return Err(anyhow!(
937 "Unknown DATEADD unit: {}. Use: day, month, year, hour, minute, second",
938 unit
939 ))
940 }
941 };
942
943 Ok(DataValue::DateTime(
945 result_date.format("%Y-%m-%d %H:%M:%S").to_string(),
946 ))
947 }
948 "TEXTJOIN" => {
949 if args.len() < 3 {
950 return Err(anyhow!("TEXTJOIN requires at least 3 arguments: delimiter, ignore_empty, text1, [text2, ...]"));
951 }
952
953 let delimiter = match self.evaluate(&args[0], row_index)? {
955 DataValue::String(s) => s,
956 DataValue::InternedString(s) => s.to_string(),
957 DataValue::Integer(n) => n.to_string(),
958 DataValue::Float(f) => f.to_string(),
959 DataValue::Boolean(b) => b.to_string(),
960 DataValue::Null => String::new(),
961 _ => String::new(),
962 };
963
964 let ignore_empty = match self.evaluate(&args[1], row_index)? {
966 DataValue::Integer(n) => n != 0,
967 DataValue::Float(f) => f != 0.0,
968 DataValue::Boolean(b) => b,
969 DataValue::String(s) => {
970 !s.is_empty() && s != "0" && s.to_lowercase() != "false"
971 }
972 DataValue::InternedString(s) => {
973 !s.is_empty() && s.as_str() != "0" && s.to_lowercase() != "false"
974 }
975 DataValue::Null => false,
976 _ => true,
977 };
978
979 let mut values = Vec::new();
981 for i in 2..args.len() {
982 let value = self.evaluate(&args[i], row_index)?;
983 let string_value = match value {
984 DataValue::String(s) => Some(s),
985 DataValue::InternedString(s) => Some(s.to_string()),
986 DataValue::Integer(n) => Some(n.to_string()),
987 DataValue::Float(f) => Some(f.to_string()),
988 DataValue::Boolean(b) => Some(b.to_string()),
989 DataValue::DateTime(dt) => Some(dt),
990 DataValue::Null => {
991 if ignore_empty {
992 None
993 } else {
994 Some(String::new())
995 }
996 }
997 _ => {
998 if ignore_empty {
999 None
1000 } else {
1001 Some(String::new())
1002 }
1003 }
1004 };
1005
1006 if let Some(s) = string_value {
1007 if !ignore_empty || !s.is_empty() {
1008 values.push(s);
1009 }
1010 }
1011 }
1012
1013 Ok(DataValue::String(values.join(&delimiter)))
1014 }
1015 "PI" => {
1016 if !args.is_empty() {
1018 return Err(anyhow!("PI() takes no arguments"));
1019 }
1020 Ok(DataValue::Float(std::f64::consts::PI))
1021 }
1022 "EULER" => {
1023 if !args.is_empty() {
1025 return Err(anyhow!("EULER() takes no arguments"));
1026 }
1027 Ok(DataValue::Float(std::f64::consts::E))
1028 }
1029 "TAU" => {
1030 if !args.is_empty() {
1032 return Err(anyhow!("TAU() takes no arguments"));
1033 }
1034 Ok(DataValue::Float(std::f64::consts::TAU))
1035 }
1036 "PHI" => {
1037 if !args.is_empty() {
1039 return Err(anyhow!("PHI() takes no arguments"));
1040 }
1041 Ok(DataValue::Float(1.618033988749895))
1042 }
1043 "SQRT2" => {
1044 if !args.is_empty() {
1046 return Err(anyhow!("SQRT2() takes no arguments"));
1047 }
1048 Ok(DataValue::Float(std::f64::consts::SQRT_2))
1049 }
1050 "LN2" => {
1051 if !args.is_empty() {
1053 return Err(anyhow!("LN2() takes no arguments"));
1054 }
1055 Ok(DataValue::Float(std::f64::consts::LN_2))
1056 }
1057 "LN10" => {
1058 if !args.is_empty() {
1060 return Err(anyhow!("LN10() takes no arguments"));
1061 }
1062 Ok(DataValue::Float(std::f64::consts::LN_10))
1063 }
1064 "C" | "SPEED_OF_LIGHT" => {
1066 if !args.is_empty() {
1068 return Err(anyhow!("C() takes no arguments"));
1069 }
1070 Ok(DataValue::Float(299792458.0))
1071 }
1072 "G" | "GRAVITATIONAL_CONSTANT" => {
1073 if !args.is_empty() {
1075 return Err(anyhow!("G() takes no arguments"));
1076 }
1077 Ok(DataValue::Float(6.67430e-11))
1078 }
1079 "H" | "PLANCK" => {
1080 if !args.is_empty() {
1082 return Err(anyhow!("PLANCK() takes no arguments"));
1083 }
1084 Ok(DataValue::Float(6.62607015e-34))
1085 }
1086 "HBAR" => {
1087 if !args.is_empty() {
1089 return Err(anyhow!("HBAR() takes no arguments"));
1090 }
1091 Ok(DataValue::Float(1.054571817e-34))
1092 }
1093 "K" | "BOLTZMANN" => {
1094 if !args.is_empty() {
1096 return Err(anyhow!("BOLTZMANN() takes no arguments"));
1097 }
1098 Ok(DataValue::Float(1.380649e-23))
1099 }
1100 "NA" | "AVOGADRO" => {
1101 if !args.is_empty() {
1103 return Err(anyhow!("AVOGADRO() takes no arguments"));
1104 }
1105 Ok(DataValue::Float(6.02214076e23))
1106 }
1107 "R" | "GAS_CONSTANT" => {
1108 if !args.is_empty() {
1110 return Err(anyhow!("R() takes no arguments"));
1111 }
1112 Ok(DataValue::Float(8.314462618))
1113 }
1114 "E0" | "EPSILON0" | "PERMITTIVITY" => {
1116 if !args.is_empty() {
1118 return Err(anyhow!("E0() takes no arguments"));
1119 }
1120 Ok(DataValue::Float(8.8541878128e-12))
1121 }
1122 "MU0" | "PERMEABILITY" => {
1123 if !args.is_empty() {
1125 return Err(anyhow!("MU0() takes no arguments"));
1126 }
1127 Ok(DataValue::Float(1.25663706212e-6))
1128 }
1129 "QE" | "ELEMENTARY_CHARGE" => {
1130 if !args.is_empty() {
1132 return Err(anyhow!("QE() takes no arguments"));
1133 }
1134 Ok(DataValue::Float(1.602176634e-19))
1135 }
1136 "ME" | "MASS_ELECTRON" => {
1138 if !args.is_empty() {
1140 return Err(anyhow!("ME() takes no arguments"));
1141 }
1142 Ok(DataValue::Float(9.1093837015e-31))
1143 }
1144 "MP" | "MASS_PROTON" => {
1145 if !args.is_empty() {
1147 return Err(anyhow!("MP() takes no arguments"));
1148 }
1149 Ok(DataValue::Float(1.67262192369e-27))
1150 }
1151 "MN" | "MASS_NEUTRON" => {
1152 if !args.is_empty() {
1154 return Err(anyhow!("MN() takes no arguments"));
1155 }
1156 Ok(DataValue::Float(1.67492749804e-27))
1157 }
1158 "AMU" | "ATOMIC_MASS_UNIT" => {
1159 if !args.is_empty() {
1161 return Err(anyhow!("AMU() takes no arguments"));
1162 }
1163 Ok(DataValue::Float(1.66053906660e-27))
1164 }
1165 "ALPHA" | "FINE_STRUCTURE" => {
1167 if !args.is_empty() {
1169 return Err(anyhow!("ALPHA() takes no arguments"));
1170 }
1171 Ok(DataValue::Float(7.2973525693e-3))
1172 }
1173 "RY" | "RYDBERG" => {
1174 if !args.is_empty() {
1176 return Err(anyhow!("RYDBERG() takes no arguments"));
1177 }
1178 Ok(DataValue::Float(10973731.568160))
1179 }
1180 "SIGMA" | "STEFAN_BOLTZMANN" => {
1181 if !args.is_empty() {
1183 return Err(anyhow!("SIGMA() takes no arguments"));
1184 }
1185 Ok(DataValue::Float(5.670374419e-8))
1186 }
1187 "DEGREES" => {
1189 if args.len() != 1 {
1191 return Err(anyhow!("DEGREES requires exactly 1 argument"));
1192 }
1193 let radians = match self.evaluate(&args[0], row_index)? {
1194 DataValue::Integer(n) => n as f64,
1195 DataValue::Float(f) => f,
1196 _ => return Err(anyhow!("DEGREES requires a numeric argument")),
1197 };
1198 Ok(DataValue::Float(radians * 180.0 / std::f64::consts::PI))
1199 }
1200 "RADIANS" => {
1201 if args.len() != 1 {
1203 return Err(anyhow!("RADIANS requires exactly 1 argument"));
1204 }
1205 let degrees = match self.evaluate(&args[0], row_index)? {
1206 DataValue::Integer(n) => n as f64,
1207 DataValue::Float(f) => f,
1208 _ => return Err(anyhow!("RADIANS requires a numeric argument")),
1209 };
1210 Ok(DataValue::Float(degrees * std::f64::consts::PI / 180.0))
1211 }
1212 "MID" => {
1213 if args.len() != 3 {
1215 return Err(anyhow!(
1216 "MID requires exactly 3 arguments: text, start_position, length"
1217 ));
1218 }
1219
1220 let text = match self.evaluate(&args[0], row_index)? {
1221 DataValue::String(s) => s,
1222 DataValue::InternedString(s) => s.to_string(),
1223 DataValue::Integer(n) => n.to_string(),
1224 DataValue::Float(f) => f.to_string(),
1225 DataValue::Null => String::new(),
1226 _ => return Err(anyhow!("MID first argument must be convertible to text")),
1227 };
1228
1229 let start_pos = match self.evaluate(&args[1], row_index)? {
1230 DataValue::Integer(n) => n,
1231 DataValue::Float(f) => f as i64,
1232 _ => return Err(anyhow!("MID start_position must be a number")),
1233 };
1234
1235 let length = match self.evaluate(&args[2], row_index)? {
1236 DataValue::Integer(n) => n,
1237 DataValue::Float(f) => f as i64,
1238 _ => return Err(anyhow!("MID length must be a number")),
1239 };
1240
1241 if start_pos < 1 {
1243 return Err(anyhow!("MID start_position must be >= 1"));
1244 }
1245 if length < 0 {
1246 return Err(anyhow!("MID length must be >= 0"));
1247 }
1248
1249 let start_idx = (start_pos - 1) as usize;
1251 let chars: Vec<char> = text.chars().collect();
1252
1253 if start_idx >= chars.len() {
1255 return Ok(DataValue::String(String::new()));
1256 }
1257
1258 let end_idx = std::cmp::min(start_idx + length as usize, chars.len());
1260 let result: String = chars[start_idx..end_idx].iter().collect();
1261
1262 Ok(DataValue::String(result))
1263 }
1264 "UPPER" => {
1265 if args.len() != 1 {
1266 return Err(anyhow!("UPPER requires exactly 1 argument"));
1267 }
1268
1269 let text = match self.evaluate(&args[0], row_index)? {
1270 DataValue::String(s) => s,
1271 DataValue::InternedString(s) => s.to_string(),
1272 DataValue::Integer(n) => n.to_string(),
1273 DataValue::Float(f) => f.to_string(),
1274 DataValue::Null => String::new(),
1275 _ => return Err(anyhow!("UPPER argument must be convertible to text")),
1276 };
1277
1278 Ok(DataValue::String(text.to_uppercase()))
1279 }
1280 "LOWER" => {
1281 if args.len() != 1 {
1282 return Err(anyhow!("LOWER requires exactly 1 argument"));
1283 }
1284
1285 let text = match self.evaluate(&args[0], row_index)? {
1286 DataValue::String(s) => s,
1287 DataValue::InternedString(s) => s.to_string(),
1288 DataValue::Integer(n) => n.to_string(),
1289 DataValue::Float(f) => f.to_string(),
1290 DataValue::Null => String::new(),
1291 _ => return Err(anyhow!("LOWER argument must be convertible to text")),
1292 };
1293
1294 Ok(DataValue::String(text.to_lowercase()))
1295 }
1296 "TRIM" => {
1297 if args.len() != 1 {
1298 return Err(anyhow!("TRIM requires exactly 1 argument"));
1299 }
1300
1301 let text = match self.evaluate(&args[0], row_index)? {
1302 DataValue::String(s) => s,
1303 DataValue::InternedString(s) => s.to_string(),
1304 DataValue::Integer(n) => n.to_string(),
1305 DataValue::Float(f) => f.to_string(),
1306 DataValue::Null => String::new(),
1307 _ => return Err(anyhow!("TRIM argument must be convertible to text")),
1308 };
1309
1310 Ok(DataValue::String(text.trim().to_string()))
1311 }
1312 _ => Err(anyhow!("Unknown function: {}", name)),
1313 }
1314 }
1315
1316 fn evaluate_method_call(
1318 &self,
1319 object: &str,
1320 method: &str,
1321 args: &[SqlExpression],
1322 row_index: usize,
1323 ) -> Result<DataValue> {
1324 let col_index = self.table.get_column_index(object).ok_or_else(|| {
1326 let suggestion = self.find_similar_column(object);
1327 match suggestion {
1328 Some(similar) => {
1329 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
1330 }
1331 None => anyhow!("Column '{}' not found", object),
1332 }
1333 })?;
1334
1335 let cell_value = self.table.get_value(row_index, col_index).cloned();
1336
1337 self.evaluate_method_on_value(
1338 &cell_value.unwrap_or(DataValue::Null),
1339 method,
1340 args,
1341 row_index,
1342 )
1343 }
1344
1345 fn evaluate_method_on_value(
1347 &self,
1348 value: &DataValue,
1349 method: &str,
1350 args: &[SqlExpression],
1351 row_index: usize,
1352 ) -> Result<DataValue> {
1353 match method.to_lowercase().as_str() {
1354 "trim" | "trimstart" | "trimend" => {
1355 if !args.is_empty() {
1356 return Err(anyhow!("{} takes no arguments", method));
1357 }
1358
1359 let str_val = match value {
1361 DataValue::String(s) => s.clone(),
1362 DataValue::InternedString(s) => s.to_string(),
1363 DataValue::Integer(n) => n.to_string(),
1364 DataValue::Float(f) => f.to_string(),
1365 DataValue::Boolean(b) => b.to_string(),
1366 DataValue::DateTime(dt) => dt.clone(),
1367 DataValue::Null => return Ok(DataValue::Null),
1368 };
1369
1370 let result = match method.to_lowercase().as_str() {
1371 "trim" => str_val.trim().to_string(),
1372 "trimstart" => str_val.trim_start().to_string(),
1373 "trimend" => str_val.trim_end().to_string(),
1374 _ => unreachable!(),
1375 };
1376
1377 Ok(DataValue::String(result))
1378 }
1379 "length" => {
1380 if !args.is_empty() {
1381 return Err(anyhow!("Length takes no arguments"));
1382 }
1383
1384 let len = match value {
1386 DataValue::String(s) => s.len(),
1387 DataValue::InternedString(s) => s.len(),
1388 DataValue::Integer(n) => n.to_string().len(),
1389 DataValue::Float(f) => f.to_string().len(),
1390 DataValue::Boolean(b) => b.to_string().len(),
1391 DataValue::DateTime(dt) => dt.len(),
1392 DataValue::Null => return Ok(DataValue::Integer(0)),
1393 };
1394
1395 Ok(DataValue::Integer(len as i64))
1396 }
1397 "indexof" => {
1398 if args.len() != 1 {
1399 return Err(anyhow!("IndexOf requires exactly 1 argument"));
1400 }
1401
1402 let search_str = match self.evaluate(&args[0], row_index)? {
1404 DataValue::String(s) => s,
1405 DataValue::InternedString(s) => s.to_string(),
1406 DataValue::Integer(n) => n.to_string(),
1407 DataValue::Float(f) => f.to_string(),
1408 _ => return Err(anyhow!("IndexOf argument must be a string")),
1409 };
1410
1411 let str_val = match value {
1413 DataValue::String(s) => s.clone(),
1414 DataValue::InternedString(s) => s.to_string(),
1415 DataValue::Integer(n) => n.to_string(),
1416 DataValue::Float(f) => f.to_string(),
1417 DataValue::Boolean(b) => b.to_string(),
1418 DataValue::DateTime(dt) => dt.clone(),
1419 DataValue::Null => return Ok(DataValue::Integer(-1)),
1420 };
1421
1422 let index = str_val.find(&search_str).map(|i| i as i64).unwrap_or(-1);
1423
1424 Ok(DataValue::Integer(index))
1425 }
1426 "contains" => {
1427 if args.len() != 1 {
1428 return Err(anyhow!("Contains requires exactly 1 argument"));
1429 }
1430
1431 let search_str = match self.evaluate(&args[0], row_index)? {
1433 DataValue::String(s) => s,
1434 DataValue::InternedString(s) => s.to_string(),
1435 DataValue::Integer(n) => n.to_string(),
1436 DataValue::Float(f) => f.to_string(),
1437 _ => return Err(anyhow!("Contains argument must be a string")),
1438 };
1439
1440 let str_val = match value {
1442 DataValue::String(s) => s.clone(),
1443 DataValue::InternedString(s) => s.to_string(),
1444 DataValue::Integer(n) => n.to_string(),
1445 DataValue::Float(f) => f.to_string(),
1446 DataValue::Boolean(b) => b.to_string(),
1447 DataValue::DateTime(dt) => dt.clone(),
1448 DataValue::Null => return Ok(DataValue::Boolean(false)),
1449 };
1450
1451 let result = str_val.to_lowercase().contains(&search_str.to_lowercase());
1453 Ok(DataValue::Boolean(result))
1454 }
1455 "startswith" => {
1456 if args.len() != 1 {
1457 return Err(anyhow!("StartsWith requires exactly 1 argument"));
1458 }
1459
1460 let prefix = match self.evaluate(&args[0], row_index)? {
1462 DataValue::String(s) => s,
1463 DataValue::InternedString(s) => s.to_string(),
1464 DataValue::Integer(n) => n.to_string(),
1465 DataValue::Float(f) => f.to_string(),
1466 _ => return Err(anyhow!("StartsWith argument must be a string")),
1467 };
1468
1469 let str_val = match value {
1471 DataValue::String(s) => s.clone(),
1472 DataValue::InternedString(s) => s.to_string(),
1473 DataValue::Integer(n) => n.to_string(),
1474 DataValue::Float(f) => f.to_string(),
1475 DataValue::Boolean(b) => b.to_string(),
1476 DataValue::DateTime(dt) => dt.clone(),
1477 DataValue::Null => return Ok(DataValue::Boolean(false)),
1478 };
1479
1480 let result = str_val.to_lowercase().starts_with(&prefix.to_lowercase());
1482 Ok(DataValue::Boolean(result))
1483 }
1484 "endswith" => {
1485 if args.len() != 1 {
1486 return Err(anyhow!("EndsWith requires exactly 1 argument"));
1487 }
1488
1489 let suffix = match self.evaluate(&args[0], row_index)? {
1491 DataValue::String(s) => s,
1492 DataValue::InternedString(s) => s.to_string(),
1493 DataValue::Integer(n) => n.to_string(),
1494 DataValue::Float(f) => f.to_string(),
1495 _ => return Err(anyhow!("EndsWith argument must be a string")),
1496 };
1497
1498 let str_val = match value {
1500 DataValue::String(s) => s.clone(),
1501 DataValue::InternedString(s) => s.to_string(),
1502 DataValue::Integer(n) => n.to_string(),
1503 DataValue::Float(f) => f.to_string(),
1504 DataValue::Boolean(b) => b.to_string(),
1505 DataValue::DateTime(dt) => dt.clone(),
1506 DataValue::Null => return Ok(DataValue::Boolean(false)),
1507 };
1508
1509 let result = str_val.to_lowercase().ends_with(&suffix.to_lowercase());
1511 Ok(DataValue::Boolean(result))
1512 }
1513 _ => Err(anyhow!("Unsupported method: {}", method)),
1514 }
1515 }
1516
1517 fn evaluate_case_expression(
1519 &self,
1520 when_branches: &[crate::sql::recursive_parser::WhenBranch],
1521 else_branch: &Option<Box<SqlExpression>>,
1522 row_index: usize,
1523 ) -> Result<DataValue> {
1524 debug!(
1525 "ArithmeticEvaluator: evaluating CASE expression for row {}",
1526 row_index
1527 );
1528
1529 for branch in when_branches {
1531 let condition_result = self.evaluate_condition_as_bool(&branch.condition, row_index)?;
1533
1534 if condition_result {
1535 debug!("CASE: WHEN condition matched, evaluating result expression");
1536 return self.evaluate(&branch.result, row_index);
1537 }
1538 }
1539
1540 match else_branch {
1542 Some(else_expr) => {
1543 debug!("CASE: No WHEN matched, evaluating ELSE expression");
1544 self.evaluate(else_expr, row_index)
1545 }
1546 None => {
1547 debug!("CASE: No WHEN matched and no ELSE, returning NULL");
1548 Ok(DataValue::Null)
1549 }
1550 }
1551 }
1552
1553 fn evaluate_condition_as_bool(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
1555 let value = self.evaluate(expr, row_index)?;
1556
1557 match value {
1558 DataValue::Boolean(b) => Ok(b),
1559 DataValue::Integer(i) => Ok(i != 0),
1560 DataValue::Float(f) => Ok(f != 0.0),
1561 DataValue::Null => Ok(false),
1562 DataValue::String(s) => Ok(!s.is_empty()),
1563 DataValue::InternedString(s) => Ok(!s.is_empty()),
1564 _ => Ok(true), }
1566 }
1567}
1568
1569#[cfg(test)]
1570mod tests {
1571 use super::*;
1572 use crate::data::datatable::{DataColumn, DataRow};
1573
1574 fn create_test_table() -> DataTable {
1575 let mut table = DataTable::new("test");
1576 table.add_column(DataColumn::new("a"));
1577 table.add_column(DataColumn::new("b"));
1578 table.add_column(DataColumn::new("c"));
1579
1580 table
1581 .add_row(DataRow::new(vec![
1582 DataValue::Integer(10),
1583 DataValue::Float(2.5),
1584 DataValue::Integer(4),
1585 ]))
1586 .unwrap();
1587
1588 table
1589 }
1590
1591 #[test]
1592 fn test_evaluate_column() {
1593 let table = create_test_table();
1594 let evaluator = ArithmeticEvaluator::new(&table);
1595
1596 let expr = SqlExpression::Column("a".to_string());
1597 let result = evaluator.evaluate(&expr, 0).unwrap();
1598 assert_eq!(result, DataValue::Integer(10));
1599 }
1600
1601 #[test]
1602 fn test_evaluate_number_literal() {
1603 let table = create_test_table();
1604 let evaluator = ArithmeticEvaluator::new(&table);
1605
1606 let expr = SqlExpression::NumberLiteral("42".to_string());
1607 let result = evaluator.evaluate(&expr, 0).unwrap();
1608 assert_eq!(result, DataValue::Integer(42));
1609
1610 let expr = SqlExpression::NumberLiteral("3.14".to_string());
1611 let result = evaluator.evaluate(&expr, 0).unwrap();
1612 assert_eq!(result, DataValue::Float(3.14));
1613 }
1614
1615 #[test]
1616 fn test_add_values() {
1617 let table = create_test_table();
1618 let evaluator = ArithmeticEvaluator::new(&table);
1619
1620 let result = evaluator
1622 .add_values(&DataValue::Integer(5), &DataValue::Integer(3))
1623 .unwrap();
1624 assert_eq!(result, DataValue::Integer(8));
1625
1626 let result = evaluator
1628 .add_values(&DataValue::Integer(5), &DataValue::Float(2.5))
1629 .unwrap();
1630 assert_eq!(result, DataValue::Float(7.5));
1631 }
1632
1633 #[test]
1634 fn test_multiply_values() {
1635 let table = create_test_table();
1636 let evaluator = ArithmeticEvaluator::new(&table);
1637
1638 let result = evaluator
1640 .multiply_values(&DataValue::Integer(4), &DataValue::Float(2.5))
1641 .unwrap();
1642 assert_eq!(result, DataValue::Float(10.0));
1643 }
1644
1645 #[test]
1646 fn test_divide_values() {
1647 let table = create_test_table();
1648 let evaluator = ArithmeticEvaluator::new(&table);
1649
1650 let result = evaluator
1652 .divide_values(&DataValue::Integer(10), &DataValue::Integer(2))
1653 .unwrap();
1654 assert_eq!(result, DataValue::Integer(5));
1655
1656 let result = evaluator
1658 .divide_values(&DataValue::Integer(10), &DataValue::Integer(3))
1659 .unwrap();
1660 assert_eq!(result, DataValue::Float(10.0 / 3.0));
1661 }
1662
1663 #[test]
1664 fn test_division_by_zero() {
1665 let table = create_test_table();
1666 let evaluator = ArithmeticEvaluator::new(&table);
1667
1668 let result = evaluator.divide_values(&DataValue::Integer(10), &DataValue::Integer(0));
1669 assert!(result.is_err());
1670 assert!(result.unwrap_err().to_string().contains("Division by zero"));
1671 }
1672
1673 #[test]
1674 fn test_binary_op_expression() {
1675 let table = create_test_table();
1676 let evaluator = ArithmeticEvaluator::new(&table);
1677
1678 let expr = SqlExpression::BinaryOp {
1680 left: Box::new(SqlExpression::Column("a".to_string())),
1681 op: "*".to_string(),
1682 right: Box::new(SqlExpression::Column("b".to_string())),
1683 };
1684
1685 let result = evaluator.evaluate(&expr, 0).unwrap();
1686 assert_eq!(result, DataValue::Float(25.0));
1687 }
1688}