1use crate::config::global::get_date_notation;
2use crate::data::data_view::DataView;
3use crate::data::datatable::{DataTable, DataValue};
4use crate::data::value_comparisons::compare_with_op;
5use crate::sql::aggregate_functions::AggregateFunctionRegistry; use crate::sql::aggregates::AggregateRegistry; use crate::sql::functions::FunctionRegistry;
8use crate::sql::parser::ast::{ColumnRef, WindowSpec};
9use crate::sql::recursive_parser::SqlExpression;
10use crate::sql::window_context::WindowContext;
11use crate::sql::window_functions::{ExpressionEvaluator, WindowFunctionRegistry};
12use anyhow::{anyhow, Result};
13use std::collections::{HashMap, HashSet};
14use std::sync::Arc;
15use std::time::Instant;
16use tracing::{debug, info};
17
18pub struct ArithmeticEvaluator<'a> {
21 table: &'a DataTable,
22 _date_notation: String,
23 function_registry: Arc<FunctionRegistry>,
24 aggregate_registry: Arc<AggregateRegistry>, new_aggregate_registry: Arc<AggregateFunctionRegistry>, window_function_registry: Arc<WindowFunctionRegistry>,
27 visible_rows: Option<Vec<usize>>, window_contexts: HashMap<u64, Arc<WindowContext>>, table_aliases: HashMap<String, String>, }
31
32impl<'a> ArithmeticEvaluator<'a> {
33 #[must_use]
34 pub fn new(table: &'a DataTable) -> Self {
35 Self {
36 table,
37 _date_notation: get_date_notation(),
38 function_registry: Arc::new(FunctionRegistry::new()),
39 aggregate_registry: Arc::new(AggregateRegistry::new()),
40 new_aggregate_registry: Arc::new(AggregateFunctionRegistry::new()),
41 window_function_registry: Arc::new(WindowFunctionRegistry::new()),
42 visible_rows: None,
43 window_contexts: HashMap::new(),
44 table_aliases: HashMap::new(),
45 }
46 }
47
48 #[must_use]
49 pub fn with_date_notation(table: &'a DataTable, date_notation: String) -> Self {
50 Self {
51 table,
52 _date_notation: date_notation,
53 function_registry: Arc::new(FunctionRegistry::new()),
54 aggregate_registry: Arc::new(AggregateRegistry::new()),
55 new_aggregate_registry: Arc::new(AggregateFunctionRegistry::new()),
56 window_function_registry: Arc::new(WindowFunctionRegistry::new()),
57 visible_rows: None,
58 window_contexts: HashMap::new(),
59 table_aliases: HashMap::new(),
60 }
61 }
62
63 #[must_use]
65 pub fn with_visible_rows(mut self, rows: Vec<usize>) -> Self {
66 self.visible_rows = Some(rows);
67 self
68 }
69
70 #[must_use]
72 pub fn with_table_aliases(mut self, aliases: HashMap<String, String>) -> Self {
73 self.table_aliases = aliases;
74 self
75 }
76
77 #[must_use]
78 pub fn with_date_notation_and_registry(
79 table: &'a DataTable,
80 date_notation: String,
81 function_registry: Arc<FunctionRegistry>,
82 ) -> Self {
83 Self {
84 table,
85 _date_notation: date_notation,
86 function_registry,
87 aggregate_registry: Arc::new(AggregateRegistry::new()),
88 new_aggregate_registry: Arc::new(AggregateFunctionRegistry::new()),
89 window_function_registry: Arc::new(WindowFunctionRegistry::new()),
90 visible_rows: None,
91 window_contexts: HashMap::new(),
92 table_aliases: HashMap::new(),
93 }
94 }
95
96 fn find_similar_column(&self, name: &str) -> Option<String> {
98 let columns = self.table.column_names();
99 let mut best_match: Option<(String, usize)> = None;
100
101 for col in columns {
102 let distance = self.edit_distance(&col.to_lowercase(), &name.to_lowercase());
103 let max_distance = if name.len() > 10 { 3 } else { 2 };
106 if distance <= max_distance {
107 match &best_match {
108 None => best_match = Some((col, distance)),
109 Some((_, best_dist)) if distance < *best_dist => {
110 best_match = Some((col, distance));
111 }
112 _ => {}
113 }
114 }
115 }
116
117 best_match.map(|(name, _)| name)
118 }
119
120 fn edit_distance(&self, s1: &str, s2: &str) -> usize {
122 crate::sql::functions::string_methods::EditDistanceFunction::calculate_edit_distance(s1, s2)
124 }
125
126 pub fn evaluate(&mut self, expr: &SqlExpression, row_index: usize) -> Result<DataValue> {
128 debug!(
129 "ArithmeticEvaluator: evaluating {:?} for row {}",
130 expr, row_index
131 );
132
133 match expr {
134 SqlExpression::Column(column_ref) => self.evaluate_column_ref(column_ref, row_index),
135 SqlExpression::StringLiteral(s) => Ok(DataValue::String(s.clone())),
136 SqlExpression::BooleanLiteral(b) => Ok(DataValue::Boolean(*b)),
137 SqlExpression::NumberLiteral(n) => self.evaluate_number_literal(n),
138 SqlExpression::Null => Ok(DataValue::Null),
139 SqlExpression::BinaryOp { left, op, right } => {
140 self.evaluate_binary_op(left, op, right, row_index)
141 }
142 SqlExpression::FunctionCall {
143 name,
144 args,
145 distinct,
146 } => self.evaluate_function_with_distinct(name, args, *distinct, row_index),
147 SqlExpression::WindowFunction {
148 name,
149 args,
150 window_spec,
151 } => self.evaluate_window_function(name, args, window_spec, row_index),
152 SqlExpression::MethodCall {
153 object,
154 method,
155 args,
156 } => self.evaluate_method_call(object, method, args, row_index),
157 SqlExpression::ChainedMethodCall { base, method, args } => {
158 let base_value = self.evaluate(base, row_index)?;
160 self.evaluate_method_on_value(&base_value, method, args, row_index)
161 }
162 SqlExpression::Between { expr, lower, upper } => {
163 let val = self.evaluate(expr, row_index)?;
164 let lo = self.evaluate(lower, row_index)?;
165 let hi = self.evaluate(upper, row_index)?;
166 let ge = compare_with_op(&val, &lo, ">=", false);
167 let le = compare_with_op(&val, &hi, "<=", false);
168 Ok(DataValue::Boolean(ge && le))
169 }
170 SqlExpression::Not { expr } => {
174 let inner = self.evaluate(expr, row_index)?;
175 match inner {
176 DataValue::Null => Ok(DataValue::Null),
177 other => Ok(DataValue::Boolean(!self.to_bool(&other)?)),
178 }
179 }
180 SqlExpression::InList { expr, values } => {
186 let val = self.evaluate(expr, row_index)?;
187 for v in values {
188 let item = self.evaluate(v, row_index)?;
189 if compare_with_op(&val, &item, "=", false) {
190 return Ok(DataValue::Boolean(true));
191 }
192 }
193 Ok(DataValue::Boolean(false))
194 }
195 SqlExpression::NotInList { expr, values } => {
196 let val = self.evaluate(expr, row_index)?;
197 for v in values {
198 let item = self.evaluate(v, row_index)?;
199 if compare_with_op(&val, &item, "=", false) {
200 return Ok(DataValue::Boolean(false));
201 }
202 }
203 Ok(DataValue::Boolean(true))
204 }
205 SqlExpression::CaseExpression {
206 when_branches,
207 else_branch,
208 } => self.evaluate_case_expression(when_branches, else_branch, row_index),
209 SqlExpression::SimpleCaseExpression {
210 expr,
211 when_branches,
212 else_branch,
213 } => self.evaluate_simple_case_expression(expr, when_branches, else_branch, row_index),
214 SqlExpression::DateTimeConstructor {
215 year,
216 month,
217 day,
218 hour,
219 minute,
220 second,
221 } => self.evaluate_datetime_constructor(*year, *month, *day, *hour, *minute, *second),
222 SqlExpression::DateTimeToday {
223 hour,
224 minute,
225 second,
226 } => self.evaluate_datetime_today(*hour, *minute, *second),
227 _ => Err(anyhow!(
228 "Unsupported expression type for arithmetic evaluation: {:?}",
229 expr
230 )),
231 }
232 }
233
234 fn evaluate_column_ref(&self, column_ref: &ColumnRef, row_index: usize) -> Result<DataValue> {
236 if let Some(table_prefix) = &column_ref.table_prefix {
237 let actual_table = self
239 .table_aliases
240 .get(table_prefix)
241 .map(|s| s.as_str())
242 .unwrap_or(table_prefix);
243
244 let qualified_name = format!("{}.{}", actual_table, column_ref.name);
246
247 if let Some(col_idx) = self.table.find_column_by_qualified_name(&qualified_name) {
248 debug!(
249 "Resolved {}.{} -> '{}' at index {}",
250 table_prefix, column_ref.name, qualified_name, col_idx
251 );
252 return self
253 .table
254 .get_value(row_index, col_idx)
255 .ok_or_else(|| anyhow!("Row {} out of bounds", row_index))
256 .map(|v| v.clone());
257 }
258
259 if let Some(col_idx) = self.table.get_column_index(&column_ref.name) {
261 debug!(
262 "Resolved {}.{} -> unqualified '{}' at index {}",
263 table_prefix, column_ref.name, column_ref.name, col_idx
264 );
265 return self
266 .table
267 .get_value(row_index, col_idx)
268 .ok_or_else(|| anyhow!("Row {} out of bounds", row_index))
269 .map(|v| v.clone());
270 }
271
272 Err(anyhow!(
274 "Column '{}' not found. Table '{}' may not support qualified column names",
275 qualified_name,
276 actual_table
277 ))
278 } else {
279 self.evaluate_column(&column_ref.name, row_index)
281 }
282 }
283
284 fn evaluate_column(&self, column_name: &str, row_index: usize) -> Result<DataValue> {
286 let resolved_column = if column_name.contains('.') {
288 if let Some(dot_pos) = column_name.rfind('.') {
290 let _table_or_alias = &column_name[..dot_pos];
291 let col_name = &column_name[dot_pos + 1..];
292
293 debug!(
296 "Resolving qualified column: {} -> {}",
297 column_name, col_name
298 );
299 col_name.to_string()
300 } else {
301 column_name.to_string()
302 }
303 } else {
304 column_name.to_string()
305 };
306
307 let col_index = if let Some(idx) = self.table.get_column_index(&resolved_column) {
308 idx
309 } else if resolved_column != column_name {
310 if let Some(idx) = self.table.get_column_index(column_name) {
312 idx
313 } else {
314 let suggestion = self.find_similar_column(&resolved_column);
315 return Err(match suggestion {
316 Some(similar) => anyhow!(
317 "Column '{}' not found. Did you mean '{}'?",
318 column_name,
319 similar
320 ),
321 None => anyhow!("Column '{}' not found", column_name),
322 });
323 }
324 } else {
325 let suggestion = self.find_similar_column(&resolved_column);
326 return Err(match suggestion {
327 Some(similar) => anyhow!(
328 "Column '{}' not found. Did you mean '{}'?",
329 column_name,
330 similar
331 ),
332 None => anyhow!("Column '{}' not found", column_name),
333 });
334 };
335
336 if row_index >= self.table.row_count() {
337 return Err(anyhow!("Row index {} out of bounds", row_index));
338 }
339
340 let row = self
341 .table
342 .get_row(row_index)
343 .ok_or_else(|| anyhow!("Row {} not found", row_index))?;
344
345 let value = row
346 .get(col_index)
347 .ok_or_else(|| anyhow!("Column index {} out of bounds for row", col_index))?;
348
349 Ok(value.clone())
350 }
351
352 fn evaluate_number_literal(&self, number_str: &str) -> Result<DataValue> {
354 if let Ok(int_val) = number_str.parse::<i64>() {
356 return Ok(DataValue::Integer(int_val));
357 }
358
359 if let Ok(float_val) = number_str.parse::<f64>() {
361 return Ok(DataValue::Float(float_val));
362 }
363
364 Err(anyhow!("Invalid number literal: {}", number_str))
365 }
366
367 fn evaluate_binary_op(
369 &mut self,
370 left: &SqlExpression,
371 op: &str,
372 right: &SqlExpression,
373 row_index: usize,
374 ) -> Result<DataValue> {
375 let left_val = self.evaluate(left, row_index)?;
376 let right_val = self.evaluate(right, row_index)?;
377
378 debug!(
379 "ArithmeticEvaluator: {} {} {}",
380 self.format_value(&left_val),
381 op,
382 self.format_value(&right_val)
383 );
384
385 match op {
386 "+" => self.add_values(&left_val, &right_val),
387 "-" => self.subtract_values(&left_val, &right_val),
388 "*" => self.multiply_values(&left_val, &right_val),
389 "/" => self.divide_values(&left_val, &right_val),
390 "%" => {
391 let args = vec![left.clone(), right.clone()];
393 self.evaluate_function("MOD", &args, row_index)
394 }
395 ">" | "<" | ">=" | "<=" | "=" | "!=" | "<>" => {
398 let result = compare_with_op(&left_val, &right_val, op, false);
399 Ok(DataValue::Boolean(result))
400 }
401 "IS NULL" => Ok(DataValue::Boolean(matches!(left_val, DataValue::Null))),
403 "IS NOT NULL" => Ok(DataValue::Boolean(!matches!(left_val, DataValue::Null))),
404 "AND" => {
406 let left_bool = self.to_bool(&left_val)?;
407 let right_bool = self.to_bool(&right_val)?;
408 Ok(DataValue::Boolean(left_bool && right_bool))
409 }
410 "OR" => {
411 let left_bool = self.to_bool(&left_val)?;
412 let right_bool = self.to_bool(&right_val)?;
413 Ok(DataValue::Boolean(left_bool || right_bool))
414 }
415 "LIKE" => {
417 let text = self.value_to_string(&left_val);
418 let pattern = self.value_to_string(&right_val);
419 let matches = self.sql_like_match(&text, &pattern);
420 Ok(DataValue::Boolean(matches))
421 }
422 _ => Err(anyhow!("Unsupported arithmetic operator: {}", op)),
423 }
424 }
425
426 fn add_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
428 if matches!(left, DataValue::Null) || matches!(right, DataValue::Null) {
430 return Ok(DataValue::Null);
431 }
432
433 match (left, right) {
434 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a + b)),
435 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 + b)),
436 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a + *b as f64)),
437 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a + b)),
438 _ => Err(anyhow!("Cannot add {:?} and {:?}", left, right)),
439 }
440 }
441
442 fn subtract_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
444 if matches!(left, DataValue::Null) || matches!(right, DataValue::Null) {
446 return Ok(DataValue::Null);
447 }
448
449 match (left, right) {
450 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a - b)),
451 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 - b)),
452 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a - *b as f64)),
453 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a - b)),
454 _ => Err(anyhow!("Cannot subtract {:?} and {:?}", left, right)),
455 }
456 }
457
458 fn multiply_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
460 if matches!(left, DataValue::Null) || matches!(right, DataValue::Null) {
462 return Ok(DataValue::Null);
463 }
464
465 match (left, right) {
466 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(DataValue::Integer(a * b)),
467 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 * b)),
468 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a * *b as f64)),
469 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a * b)),
470 _ => Err(anyhow!("Cannot multiply {:?} and {:?}", left, right)),
471 }
472 }
473
474 fn divide_values(&self, left: &DataValue, right: &DataValue) -> Result<DataValue> {
476 if matches!(left, DataValue::Null) || matches!(right, DataValue::Null) {
478 return Ok(DataValue::Null);
479 }
480
481 let is_zero = match right {
483 DataValue::Integer(0) => true,
484 DataValue::Float(f) if *f == 0.0 => true, _ => false,
486 };
487
488 if is_zero {
489 return Err(anyhow!("Division by zero"));
490 }
491
492 match (left, right) {
493 (DataValue::Integer(a), DataValue::Integer(b)) => {
494 if a % b == 0 {
496 Ok(DataValue::Integer(a / b))
497 } else {
498 Ok(DataValue::Float(*a as f64 / *b as f64))
499 }
500 }
501 (DataValue::Integer(a), DataValue::Float(b)) => Ok(DataValue::Float(*a as f64 / b)),
502 (DataValue::Float(a), DataValue::Integer(b)) => Ok(DataValue::Float(a / *b as f64)),
503 (DataValue::Float(a), DataValue::Float(b)) => Ok(DataValue::Float(a / b)),
504 _ => Err(anyhow!("Cannot divide {:?} and {:?}", left, right)),
505 }
506 }
507
508 fn format_value(&self, value: &DataValue) -> String {
510 match value {
511 DataValue::Integer(i) => i.to_string(),
512 DataValue::Float(f) => f.to_string(),
513 DataValue::String(s) => format!("'{s}'"),
514 _ => format!("{value:?}"),
515 }
516 }
517
518 fn to_bool(&self, value: &DataValue) -> Result<bool> {
520 match value {
521 DataValue::Boolean(b) => Ok(*b),
522 DataValue::Integer(i) => Ok(*i != 0),
523 DataValue::Float(f) => Ok(*f != 0.0),
524 DataValue::Null => Ok(false),
525 _ => Err(anyhow!("Cannot convert {:?} to boolean", value)),
526 }
527 }
528
529 fn value_to_string(&self, value: &DataValue) -> String {
531 match value {
532 DataValue::String(s) => s.clone(),
533 DataValue::InternedString(s) => s.to_string(),
534 DataValue::Integer(i) => i.to_string(),
535 DataValue::Float(f) => f.to_string(),
536 DataValue::Boolean(b) => b.to_string(),
537 DataValue::DateTime(dt) => dt.to_string(),
538 DataValue::Vector(v) => {
539 let components: Vec<String> = v.iter().map(|f| f.to_string()).collect();
541 format!("[{}]", components.join(","))
542 }
543 DataValue::Null => String::new(),
544 }
545 }
546
547 fn sql_like_match(&self, text: &str, pattern: &str) -> bool {
550 let pattern_chars: Vec<char> = pattern.chars().collect();
551 let text_chars: Vec<char> = text.chars().collect();
552
553 self.like_match_recursive(&text_chars, 0, &pattern_chars, 0)
554 }
555
556 fn like_match_recursive(
558 &self,
559 text: &[char],
560 text_pos: usize,
561 pattern: &[char],
562 pattern_pos: usize,
563 ) -> bool {
564 if pattern_pos >= pattern.len() {
566 return text_pos >= text.len();
567 }
568
569 if pattern[pattern_pos] == '%' {
571 if self.like_match_recursive(text, text_pos, pattern, pattern_pos + 1) {
573 return true;
574 }
575 if text_pos < text.len() {
577 return self.like_match_recursive(text, text_pos + 1, pattern, pattern_pos);
578 }
579 return false;
580 }
581
582 if text_pos >= text.len() {
584 return false;
585 }
586
587 if pattern[pattern_pos] == '_' {
589 return self.like_match_recursive(text, text_pos + 1, pattern, pattern_pos + 1);
590 }
591
592 if text[text_pos] == pattern[pattern_pos] {
594 return self.like_match_recursive(text, text_pos + 1, pattern, pattern_pos + 1);
595 }
596
597 false
598 }
599
600 fn evaluate_function_with_distinct(
602 &mut self,
603 name: &str,
604 args: &[SqlExpression],
605 distinct: bool,
606 row_index: usize,
607 ) -> Result<DataValue> {
608 if distinct {
610 let name_upper = name.to_uppercase();
611
612 if self.aggregate_registry.is_aggregate(&name_upper)
614 || self.new_aggregate_registry.contains(&name_upper)
615 {
616 return self.evaluate_aggregate_with_distinct(&name_upper, args, row_index);
617 } else {
618 return Err(anyhow!(
619 "DISTINCT can only be used with aggregate functions"
620 ));
621 }
622 }
623
624 self.evaluate_function(name, args, row_index)
626 }
627
628 fn evaluate_aggregate_with_distinct(
629 &mut self,
630 name: &str,
631 args: &[SqlExpression],
632 _row_index: usize,
633 ) -> Result<DataValue> {
634 let name_upper = name.to_uppercase();
635
636 if self.new_aggregate_registry.get(&name_upper).is_some() {
638 let rows_to_process: Vec<usize> = if let Some(ref visible) = self.visible_rows {
639 visible.clone()
640 } else {
641 (0..self.table.rows.len()).collect()
642 };
643
644 let mut vals = Vec::new();
646 for &row_idx in &rows_to_process {
647 if !args.is_empty() {
648 let value = self.evaluate(&args[0], row_idx)?;
649 vals.push(value);
650 }
651 }
652
653 let mut seen = HashSet::new();
655 let unique_values: Vec<_> = vals
656 .into_iter()
657 .filter(|v| {
658 let key = format!("{:?}", v);
659 seen.insert(key)
660 })
661 .collect();
662
663 let agg_func = self.new_aggregate_registry.get(&name_upper).unwrap();
665 let mut state = agg_func.create_state();
666
667 for value in &unique_values {
669 state.accumulate(value)?;
670 }
671
672 return Ok(state.finalize());
673 }
674
675 if self.aggregate_registry.get(&name_upper).is_some() {
677 let rows_to_process: Vec<usize> = if let Some(ref visible) = self.visible_rows {
679 visible.clone()
680 } else {
681 (0..self.table.rows.len()).collect()
682 };
683
684 if name_upper == "STRING_AGG" && args.len() >= 2 {
686 let mut state = crate::sql::aggregates::AggregateState::StringAgg(
688 if args.len() >= 2 {
690 let separator = self.evaluate(&args[1], 0)?; match separator {
692 DataValue::String(s) => crate::sql::aggregates::StringAggState::new(&s),
693 DataValue::InternedString(s) => {
694 crate::sql::aggregates::StringAggState::new(&s)
695 }
696 _ => crate::sql::aggregates::StringAggState::new(","), }
698 } else {
699 crate::sql::aggregates::StringAggState::new(",")
700 },
701 );
702
703 let mut seen_values = HashSet::new();
706
707 for &row_idx in &rows_to_process {
708 let value = self.evaluate(&args[0], row_idx)?;
709
710 if !seen_values.insert(value.clone()) {
712 continue; }
714
715 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
717 agg_func.accumulate(&mut state, &value)?;
718 }
719
720 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
722 return Ok(agg_func.finalize(state));
723 }
724
725 let mut vals = Vec::new();
728 for &row_idx in &rows_to_process {
729 if !args.is_empty() {
730 let value = self.evaluate(&args[0], row_idx)?;
731 vals.push(value);
732 }
733 }
734
735 let mut seen = HashSet::new();
737 let mut unique_values = Vec::new();
738 for value in vals {
739 if seen.insert(value.clone()) {
740 unique_values.push(value);
741 }
742 }
743
744 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
746 let mut state = agg_func.init();
747
748 for value in &unique_values {
750 agg_func.accumulate(&mut state, value)?;
751 }
752
753 return Ok(agg_func.finalize(state));
754 }
755
756 Err(anyhow!("Unknown aggregate function: {}", name))
757 }
758
759 fn evaluate_function(
760 &mut self,
761 name: &str,
762 args: &[SqlExpression],
763 row_index: usize,
764 ) -> Result<DataValue> {
765 let name_upper = name.to_uppercase();
767
768 if self.new_aggregate_registry.get(&name_upper).is_some() {
770 let rows_to_process: Vec<usize> = if let Some(ref visible) = self.visible_rows {
772 visible.clone()
773 } else {
774 (0..self.table.rows.len()).collect()
775 };
776
777 let agg_func = self.new_aggregate_registry.get(&name_upper).unwrap();
779 let mut state = agg_func.create_state();
780
781 if name_upper == "COUNT" || name_upper == "COUNT_STAR" {
783 if args.is_empty()
784 || (args.len() == 1
785 && matches!(&args[0], SqlExpression::Column(col) if col.name == "*"))
786 || (args.len() == 1
787 && matches!(&args[0], SqlExpression::StringLiteral(s) if s == "*"))
788 {
789 for _ in &rows_to_process {
791 state.accumulate(&DataValue::Integer(1))?;
792 }
793 } else {
794 for &row_idx in &rows_to_process {
796 let value = self.evaluate(&args[0], row_idx)?;
797 state.accumulate(&value)?;
798 }
799 }
800 } else {
801 if !args.is_empty() {
803 for &row_idx in &rows_to_process {
804 let value = self.evaluate(&args[0], row_idx)?;
805 state.accumulate(&value)?;
806 }
807 }
808 }
809
810 return Ok(state.finalize());
811 }
812
813 if self.aggregate_registry.get(&name_upper).is_some() {
815 let rows_to_process: Vec<usize> = if let Some(ref visible) = self.visible_rows {
817 visible.clone()
818 } else {
819 (0..self.table.rows.len()).collect()
820 };
821
822 if name_upper == "STRING_AGG" && args.len() >= 2 {
824 let mut state = crate::sql::aggregates::AggregateState::StringAgg(
826 if args.len() >= 2 {
828 let separator = self.evaluate(&args[1], 0)?; match separator {
830 DataValue::String(s) => crate::sql::aggregates::StringAggState::new(&s),
831 DataValue::InternedString(s) => {
832 crate::sql::aggregates::StringAggState::new(&s)
833 }
834 _ => crate::sql::aggregates::StringAggState::new(","), }
836 } else {
837 crate::sql::aggregates::StringAggState::new(",")
838 },
839 );
840
841 for &row_idx in &rows_to_process {
843 let value = self.evaluate(&args[0], row_idx)?;
844 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
846 agg_func.accumulate(&mut state, &value)?;
847 }
848
849 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
851 return Ok(agg_func.finalize(state));
852 }
853
854 let values = if !args.is_empty()
856 && !(args.len() == 1
857 && matches!(&args[0], SqlExpression::Column(c) if c.name == "*"))
858 {
859 let mut vals = Vec::new();
861 for &row_idx in &rows_to_process {
862 let value = self.evaluate(&args[0], row_idx)?;
863 vals.push(value);
864 }
865 Some(vals)
866 } else {
867 None
868 };
869
870 let agg_func = self.aggregate_registry.get(&name_upper).unwrap();
872 let mut state = agg_func.init();
873
874 if let Some(values) = values {
875 for value in &values {
877 agg_func.accumulate(&mut state, value)?;
878 }
879 } else {
880 for _ in &rows_to_process {
882 agg_func.accumulate(&mut state, &DataValue::Integer(1))?;
883 }
884 }
885
886 return Ok(agg_func.finalize(state));
887 }
888
889 if self.function_registry.get(name).is_some() {
891 let mut evaluated_args = Vec::new();
893 for arg in args {
894 evaluated_args.push(self.evaluate(arg, row_index)?);
895 }
896
897 let func = self.function_registry.get(name).unwrap();
899 return func.evaluate(&evaluated_args);
900 }
901
902 Err(anyhow!("Unknown function: {}", name))
904 }
905
906 pub fn get_or_create_window_context(
909 &mut self,
910 spec: &WindowSpec,
911 ) -> Result<Arc<WindowContext>> {
912 let overall_start = Instant::now();
913
914 let key = spec.compute_hash();
916
917 if let Some(context) = self.window_contexts.get(&key) {
918 info!(
919 "WindowContext cache hit for spec (lookup: {:.2}μs)",
920 overall_start.elapsed().as_micros()
921 );
922 return Ok(Arc::clone(context));
923 }
924
925 info!("WindowContext cache miss - creating new context");
926 let dataview_start = Instant::now();
927
928 let data_view = if let Some(ref visible_rows) = self.visible_rows {
937 DataView::new(Arc::new(self.table.clone())).with_rows(visible_rows.clone())
938 } else {
939 DataView::new(Arc::new(self.table.clone()))
940 };
941
942 info!(
943 "DataView creation took {:.2}μs",
944 dataview_start.elapsed().as_micros()
945 );
946 let context_start = Instant::now();
947
948 let context = WindowContext::new_with_spec(Arc::new(data_view), spec.clone())?;
950
951 info!(
952 "WindowContext::new_with_spec took {:.2}ms (rows: {})",
953 context_start.elapsed().as_secs_f64() * 1000.0,
954 self.table.row_count()
955 );
956
957 let context = Arc::new(context);
958 self.window_contexts.insert(key, Arc::clone(&context));
959
960 info!(
961 "Total WindowContext creation (cache miss) took {:.2}ms",
962 overall_start.elapsed().as_secs_f64() * 1000.0
963 );
964
965 Ok(context)
966 }
967
968 fn evaluate_window_function(
970 &mut self,
971 name: &str,
972 args: &[SqlExpression],
973 spec: &WindowSpec,
974 row_index: usize,
975 ) -> Result<DataValue> {
976 let func_start = Instant::now();
977 let name_upper = name.to_uppercase();
978
979 debug!("Looking for window function {} in registry", name_upper);
981 if let Some(window_fn_arc) = self.window_function_registry.get(&name_upper) {
982 debug!("Found window function {} in registry", name_upper);
983
984 let window_fn = window_fn_arc.as_ref();
986
987 window_fn.validate_args(args)?;
989
990 let transformed_spec = window_fn.transform_window_spec(spec, args)?;
992
993 let context = self.get_or_create_window_context(&transformed_spec)?;
995
996 struct EvaluatorAdapter<'a, 'b> {
998 evaluator: &'a mut ArithmeticEvaluator<'b>,
999 row_index: usize,
1000 }
1001
1002 impl<'a, 'b> ExpressionEvaluator for EvaluatorAdapter<'a, 'b> {
1003 fn evaluate(
1004 &mut self,
1005 expr: &SqlExpression,
1006 row_index: usize,
1007 ) -> Result<DataValue> {
1008 self.evaluator.evaluate(expr, row_index)
1009 }
1010 }
1011
1012 let mut adapter = EvaluatorAdapter {
1013 evaluator: self,
1014 row_index,
1015 };
1016
1017 let compute_start = Instant::now();
1018 let result = window_fn.compute(&context, row_index, args, &mut adapter);
1020
1021 info!(
1022 "{} (registry) evaluation: total={:.2}μs, compute={:.2}μs",
1023 name_upper,
1024 func_start.elapsed().as_micros(),
1025 compute_start.elapsed().as_micros()
1026 );
1027
1028 return result;
1029 }
1030
1031 let context_start = Instant::now();
1033 let context = self.get_or_create_window_context(spec)?;
1034 let context_time = context_start.elapsed();
1035
1036 let eval_start = Instant::now();
1037
1038 let result = match name_upper.as_str() {
1039 "LAG" => {
1040 if args.is_empty() {
1042 return Err(anyhow!("LAG requires at least 1 argument"));
1043 }
1044
1045 let column = match &args[0] {
1047 SqlExpression::Column(col) => col.clone(),
1048 _ => return Err(anyhow!("LAG first argument must be a column")),
1049 };
1050
1051 let offset = if args.len() > 1 {
1053 match self.evaluate(&args[1], row_index)? {
1054 DataValue::Integer(i) => i as i32,
1055 _ => return Err(anyhow!("LAG offset must be an integer")),
1056 }
1057 } else {
1058 1
1059 };
1060
1061 let offset_start = Instant::now();
1062 let value = context
1064 .get_offset_value(row_index, -offset, &column.name)
1065 .unwrap_or(DataValue::Null);
1066
1067 debug!(
1068 "LAG offset access took {:.2}μs (offset={})",
1069 offset_start.elapsed().as_micros(),
1070 offset
1071 );
1072
1073 Ok(value)
1074 }
1075 "LEAD" => {
1076 if args.is_empty() {
1078 return Err(anyhow!("LEAD requires at least 1 argument"));
1079 }
1080
1081 let column = match &args[0] {
1083 SqlExpression::Column(col) => col.clone(),
1084 _ => return Err(anyhow!("LEAD first argument must be a column")),
1085 };
1086
1087 let offset = if args.len() > 1 {
1089 match self.evaluate(&args[1], row_index)? {
1090 DataValue::Integer(i) => i as i32,
1091 _ => return Err(anyhow!("LEAD offset must be an integer")),
1092 }
1093 } else {
1094 1
1095 };
1096
1097 let offset_start = Instant::now();
1098 let value = context
1100 .get_offset_value(row_index, offset, &column.name)
1101 .unwrap_or(DataValue::Null);
1102
1103 debug!(
1104 "LEAD offset access took {:.2}μs (offset={})",
1105 offset_start.elapsed().as_micros(),
1106 offset
1107 );
1108
1109 Ok(value)
1110 }
1111 "ROW_NUMBER" => {
1112 Ok(DataValue::Integer(context.get_row_number(row_index) as i64))
1114 }
1115 "RANK" => {
1116 Ok(DataValue::Integer(context.get_rank(row_index)))
1118 }
1119 "DENSE_RANK" => {
1120 Ok(DataValue::Integer(context.get_dense_rank(row_index)))
1122 }
1123 "FIRST_VALUE" => {
1124 if args.is_empty() {
1126 return Err(anyhow!("FIRST_VALUE requires 1 argument"));
1127 }
1128
1129 let column = match &args[0] {
1130 SqlExpression::Column(col) => col.clone(),
1131 _ => return Err(anyhow!("FIRST_VALUE argument must be a column")),
1132 };
1133
1134 if context.has_frame() {
1136 Ok(context
1137 .get_frame_first_value(row_index, &column.name)
1138 .unwrap_or(DataValue::Null))
1139 } else {
1140 Ok(context
1141 .get_first_value(row_index, &column.name)
1142 .unwrap_or(DataValue::Null))
1143 }
1144 }
1145 "LAST_VALUE" => {
1146 if args.is_empty() {
1148 return Err(anyhow!("LAST_VALUE requires 1 argument"));
1149 }
1150
1151 let column = match &args[0] {
1152 SqlExpression::Column(col) => col.clone(),
1153 _ => return Err(anyhow!("LAST_VALUE argument must be a column")),
1154 };
1155
1156 if context.has_frame() {
1158 Ok(context
1159 .get_frame_last_value(row_index, &column.name)
1160 .unwrap_or(DataValue::Null))
1161 } else {
1162 Ok(context
1163 .get_last_value(row_index, &column.name)
1164 .unwrap_or(DataValue::Null))
1165 }
1166 }
1167 "SUM" => {
1168 if args.is_empty() {
1170 return Err(anyhow!("SUM requires 1 argument"));
1171 }
1172
1173 let column = match &args[0] {
1174 SqlExpression::Column(col) => col.clone(),
1175 _ => return Err(anyhow!("SUM argument must be a column")),
1176 };
1177
1178 if context.has_frame() {
1180 Ok(context
1181 .get_frame_sum(row_index, &column.name)
1182 .unwrap_or(DataValue::Null))
1183 } else {
1184 Ok(context
1185 .get_partition_sum(row_index, &column.name)
1186 .unwrap_or(DataValue::Null))
1187 }
1188 }
1189 "AVG" => {
1190 if args.is_empty() {
1192 return Err(anyhow!("AVG requires 1 argument"));
1193 }
1194
1195 let column = match &args[0] {
1196 SqlExpression::Column(col) => col.clone(),
1197 _ => return Err(anyhow!("AVG argument must be a column")),
1198 };
1199
1200 if context.has_frame() {
1202 Ok(context
1203 .get_frame_avg(row_index, &column.name)
1204 .unwrap_or(DataValue::Null))
1205 } else {
1206 Ok(context
1207 .get_partition_avg(row_index, &column.name)
1208 .unwrap_or(DataValue::Null))
1209 }
1210 }
1211 "STDDEV" | "STDEV" => {
1212 if args.is_empty() {
1214 return Err(anyhow!("STDDEV requires 1 argument"));
1215 }
1216
1217 let column = match &args[0] {
1218 SqlExpression::Column(col) => col.clone(),
1219 _ => return Err(anyhow!("STDDEV argument must be a column")),
1220 };
1221
1222 Ok(context
1223 .get_frame_stddev(row_index, &column.name)
1224 .unwrap_or(DataValue::Null))
1225 }
1226 "VARIANCE" | "VAR" => {
1227 if args.is_empty() {
1229 return Err(anyhow!("VARIANCE requires 1 argument"));
1230 }
1231
1232 let column = match &args[0] {
1233 SqlExpression::Column(col) => col.clone(),
1234 _ => return Err(anyhow!("VARIANCE argument must be a column")),
1235 };
1236
1237 Ok(context
1238 .get_frame_variance(row_index, &column.name)
1239 .unwrap_or(DataValue::Null))
1240 }
1241 "MIN" => {
1242 if args.is_empty() {
1244 return Err(anyhow!("MIN requires 1 argument"));
1245 }
1246
1247 let column = match &args[0] {
1248 SqlExpression::Column(col) => col.clone(),
1249 _ => return Err(anyhow!("MIN argument must be a column")),
1250 };
1251
1252 let frame_rows = context.get_frame_rows(row_index);
1253 if frame_rows.is_empty() {
1254 return Ok(DataValue::Null);
1255 }
1256
1257 let source_table = context.source();
1258 let col_idx = source_table
1259 .get_column_index(&column.name)
1260 .ok_or_else(|| anyhow!("Column '{}' not found", column.name))?;
1261
1262 let mut min_value: Option<DataValue> = None;
1263 for &row_idx in &frame_rows {
1264 if let Some(value) = source_table.get_value(row_idx, col_idx) {
1265 if !matches!(value, DataValue::Null) {
1266 match &min_value {
1267 None => min_value = Some(value.clone()),
1268 Some(current_min) => {
1269 if value < current_min {
1270 min_value = Some(value.clone());
1271 }
1272 }
1273 }
1274 }
1275 }
1276 }
1277
1278 Ok(min_value.unwrap_or(DataValue::Null))
1279 }
1280 "MAX" => {
1281 if args.is_empty() {
1283 return Err(anyhow!("MAX requires 1 argument"));
1284 }
1285
1286 let column = match &args[0] {
1287 SqlExpression::Column(col) => col.clone(),
1288 _ => return Err(anyhow!("MAX argument must be a column")),
1289 };
1290
1291 let frame_rows = context.get_frame_rows(row_index);
1292 if frame_rows.is_empty() {
1293 return Ok(DataValue::Null);
1294 }
1295
1296 let source_table = context.source();
1297 let col_idx = source_table
1298 .get_column_index(&column.name)
1299 .ok_or_else(|| anyhow!("Column '{}' not found", column.name))?;
1300
1301 let mut max_value: Option<DataValue> = None;
1302 for &row_idx in &frame_rows {
1303 if let Some(value) = source_table.get_value(row_idx, col_idx) {
1304 if !matches!(value, DataValue::Null) {
1305 match &max_value {
1306 None => max_value = Some(value.clone()),
1307 Some(current_max) => {
1308 if value > current_max {
1309 max_value = Some(value.clone());
1310 }
1311 }
1312 }
1313 }
1314 }
1315 }
1316
1317 Ok(max_value.unwrap_or(DataValue::Null))
1318 }
1319 "COUNT" => {
1320 if args.is_empty() {
1324 if context.has_frame() {
1326 Ok(context
1327 .get_frame_count(row_index, None)
1328 .unwrap_or(DataValue::Null))
1329 } else {
1330 Ok(context
1331 .get_partition_count(row_index, None)
1332 .unwrap_or(DataValue::Null))
1333 }
1334 } else {
1335 let column = match &args[0] {
1337 SqlExpression::Column(col) => {
1338 if col.name == "*" {
1339 if context.has_frame() {
1341 return Ok(context
1342 .get_frame_count(row_index, None)
1343 .unwrap_or(DataValue::Null));
1344 } else {
1345 return Ok(context
1346 .get_partition_count(row_index, None)
1347 .unwrap_or(DataValue::Null));
1348 }
1349 }
1350 col.clone()
1351 }
1352 SqlExpression::StringLiteral(s) if s == "*" => {
1353 if context.has_frame() {
1355 return Ok(context
1356 .get_frame_count(row_index, None)
1357 .unwrap_or(DataValue::Null));
1358 } else {
1359 return Ok(context
1360 .get_partition_count(row_index, None)
1361 .unwrap_or(DataValue::Null));
1362 }
1363 }
1364 _ => return Err(anyhow!("COUNT argument must be a column or *")),
1365 };
1366
1367 if context.has_frame() {
1369 Ok(context
1370 .get_frame_count(row_index, Some(&column.name))
1371 .unwrap_or(DataValue::Null))
1372 } else {
1373 Ok(context
1374 .get_partition_count(row_index, Some(&column.name))
1375 .unwrap_or(DataValue::Null))
1376 }
1377 }
1378 }
1379 _ => Err(anyhow!("Unknown window function: {}", name)),
1380 };
1381
1382 let eval_time = eval_start.elapsed();
1383
1384 info!(
1385 "{} (built-in) evaluation: total={:.2}μs, context={:.2}μs, eval={:.2}μs",
1386 name_upper,
1387 func_start.elapsed().as_micros(),
1388 context_time.as_micros(),
1389 eval_time.as_micros()
1390 );
1391
1392 result
1393 }
1394
1395 fn evaluate_method_call(
1397 &mut self,
1398 object: &str,
1399 method: &str,
1400 args: &[SqlExpression],
1401 row_index: usize,
1402 ) -> Result<DataValue> {
1403 let col_index = self.table.get_column_index(object).ok_or_else(|| {
1405 let suggestion = self.find_similar_column(object);
1406 match suggestion {
1407 Some(similar) => {
1408 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
1409 }
1410 None => anyhow!("Column '{}' not found", object),
1411 }
1412 })?;
1413
1414 let cell_value = self.table.get_value(row_index, col_index).cloned();
1415
1416 self.evaluate_method_on_value(
1417 &cell_value.unwrap_or(DataValue::Null),
1418 method,
1419 args,
1420 row_index,
1421 )
1422 }
1423
1424 fn evaluate_method_on_value(
1426 &mut self,
1427 value: &DataValue,
1428 method: &str,
1429 args: &[SqlExpression],
1430 row_index: usize,
1431 ) -> Result<DataValue> {
1432 if let Some(method_fn) = self.function_registry.get_method(method) {
1439 let mut method_args = Vec::with_capacity(args.len());
1440 for arg in args {
1441 method_args.push(self.evaluate(arg, row_index)?);
1442 }
1443 return method_fn.evaluate_method(value, &method_args);
1444 }
1445
1446 let function_name = match method.to_lowercase().as_str() {
1451 "trim" => "TRIM",
1452 "trimstart" | "trimbegin" => "TRIMSTART",
1453 "trimend" => "TRIMEND",
1454 "length" | "len" => "LENGTH",
1455 "contains" => "CONTAINS",
1456 "startswith" => "STARTSWITH",
1457 "endswith" => "ENDSWITH",
1458 "indexof" => "INDEXOF",
1459 _ => method, };
1461
1462 if self.function_registry.get(function_name).is_some() {
1464 debug!(
1465 "Proxying method '{}' through function registry as '{}'",
1466 method, function_name
1467 );
1468
1469 let mut func_args = vec![value.clone()];
1471
1472 for arg in args {
1474 func_args.push(self.evaluate(arg, row_index)?);
1475 }
1476
1477 let func = self.function_registry.get(function_name).unwrap();
1479 return func.evaluate(&func_args);
1480 }
1481
1482 Err(anyhow!(
1485 "Method '{}' not found. It should be registered in the function registry.",
1486 method
1487 ))
1488 }
1489
1490 fn evaluate_case_expression(
1492 &mut self,
1493 when_branches: &[crate::sql::recursive_parser::WhenBranch],
1494 else_branch: &Option<Box<SqlExpression>>,
1495 row_index: usize,
1496 ) -> Result<DataValue> {
1497 debug!(
1498 "ArithmeticEvaluator: evaluating CASE expression for row {}",
1499 row_index
1500 );
1501
1502 for branch in when_branches {
1504 let condition_result = self.evaluate_condition_as_bool(&branch.condition, row_index)?;
1506
1507 if condition_result {
1508 debug!("CASE: WHEN condition matched, evaluating result expression");
1509 return self.evaluate(&branch.result, row_index);
1510 }
1511 }
1512
1513 if let Some(else_expr) = else_branch {
1515 debug!("CASE: No WHEN matched, evaluating ELSE expression");
1516 self.evaluate(else_expr, row_index)
1517 } else {
1518 debug!("CASE: No WHEN matched and no ELSE, returning NULL");
1519 Ok(DataValue::Null)
1520 }
1521 }
1522
1523 fn evaluate_simple_case_expression(
1525 &mut self,
1526 expr: &Box<SqlExpression>,
1527 when_branches: &[crate::sql::parser::ast::SimpleWhenBranch],
1528 else_branch: &Option<Box<SqlExpression>>,
1529 row_index: usize,
1530 ) -> Result<DataValue> {
1531 debug!(
1532 "ArithmeticEvaluator: evaluating simple CASE expression for row {}",
1533 row_index
1534 );
1535
1536 let case_value = self.evaluate(expr, row_index)?;
1538 debug!("Simple CASE: evaluated expression to {:?}", case_value);
1539
1540 for branch in when_branches {
1542 let when_value = self.evaluate(&branch.value, row_index)?;
1544
1545 if self.values_equal(&case_value, &when_value)? {
1547 debug!("Simple CASE: WHEN value matched, evaluating result expression");
1548 return self.evaluate(&branch.result, row_index);
1549 }
1550 }
1551
1552 if let Some(else_expr) = else_branch {
1554 debug!("Simple CASE: No WHEN matched, evaluating ELSE expression");
1555 self.evaluate(else_expr, row_index)
1556 } else {
1557 debug!("Simple CASE: No WHEN matched and no ELSE, returning NULL");
1558 Ok(DataValue::Null)
1559 }
1560 }
1561
1562 fn values_equal(&self, left: &DataValue, right: &DataValue) -> Result<bool> {
1564 match (left, right) {
1565 (DataValue::Null, DataValue::Null) => Ok(true),
1566 (DataValue::Null, _) | (_, DataValue::Null) => Ok(false),
1567 (DataValue::Integer(a), DataValue::Integer(b)) => Ok(a == b),
1568 (DataValue::Float(a), DataValue::Float(b)) => Ok((a - b).abs() < f64::EPSILON),
1569 (DataValue::String(a), DataValue::String(b)) => Ok(a == b),
1570 (DataValue::Boolean(a), DataValue::Boolean(b)) => Ok(a == b),
1571 (DataValue::DateTime(a), DataValue::DateTime(b)) => Ok(a == b),
1572 (DataValue::Integer(a), DataValue::Float(b)) => {
1574 Ok((*a as f64 - b).abs() < f64::EPSILON)
1575 }
1576 (DataValue::Float(a), DataValue::Integer(b)) => {
1577 Ok((a - *b as f64).abs() < f64::EPSILON)
1578 }
1579 _ => Ok(false),
1580 }
1581 }
1582
1583 fn evaluate_condition_as_bool(
1585 &mut self,
1586 expr: &SqlExpression,
1587 row_index: usize,
1588 ) -> Result<bool> {
1589 let value = self.evaluate(expr, row_index)?;
1590
1591 match value {
1592 DataValue::Boolean(b) => Ok(b),
1593 DataValue::Integer(i) => Ok(i != 0),
1594 DataValue::Float(f) => Ok(f != 0.0),
1595 DataValue::Null => Ok(false),
1596 DataValue::String(s) => Ok(!s.is_empty()),
1597 DataValue::InternedString(s) => Ok(!s.is_empty()),
1598 _ => Ok(true), }
1600 }
1601
1602 fn evaluate_datetime_constructor(
1604 &self,
1605 year: i32,
1606 month: u32,
1607 day: u32,
1608 hour: Option<u32>,
1609 minute: Option<u32>,
1610 second: Option<u32>,
1611 ) -> Result<DataValue> {
1612 use chrono::{NaiveDate, TimeZone, Utc};
1613
1614 let date = NaiveDate::from_ymd_opt(year, month, day)
1616 .ok_or_else(|| anyhow!("Invalid date: {}-{}-{}", year, month, day))?;
1617
1618 let hour = hour.unwrap_or(0);
1620 let minute = minute.unwrap_or(0);
1621 let second = second.unwrap_or(0);
1622
1623 let naive_datetime = date
1624 .and_hms_opt(hour, minute, second)
1625 .ok_or_else(|| anyhow!("Invalid time: {}:{}:{}", hour, minute, second))?;
1626
1627 let datetime = Utc.from_utc_datetime(&naive_datetime);
1629
1630 let datetime_str = datetime.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
1632 Ok(DataValue::String(datetime_str))
1633 }
1634
1635 fn evaluate_datetime_today(
1637 &self,
1638 hour: Option<u32>,
1639 minute: Option<u32>,
1640 second: Option<u32>,
1641 ) -> Result<DataValue> {
1642 use chrono::{TimeZone, Utc};
1643
1644 let today = Utc::now().date_naive();
1646
1647 let hour = hour.unwrap_or(0);
1649 let minute = minute.unwrap_or(0);
1650 let second = second.unwrap_or(0);
1651
1652 let naive_datetime = today
1653 .and_hms_opt(hour, minute, second)
1654 .ok_or_else(|| anyhow!("Invalid time: {}:{}:{}", hour, minute, second))?;
1655
1656 let datetime = Utc.from_utc_datetime(&naive_datetime);
1658
1659 let datetime_str = datetime.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
1661 Ok(DataValue::String(datetime_str))
1662 }
1663}
1664
1665#[cfg(test)]
1666mod tests {
1667 use super::*;
1668 use crate::data::datatable::{DataColumn, DataRow};
1669
1670 fn create_test_table() -> DataTable {
1671 let mut table = DataTable::new("test");
1672 table.add_column(DataColumn::new("a"));
1673 table.add_column(DataColumn::new("b"));
1674 table.add_column(DataColumn::new("c"));
1675
1676 table
1677 .add_row(DataRow::new(vec![
1678 DataValue::Integer(10),
1679 DataValue::Float(2.5),
1680 DataValue::Integer(4),
1681 ]))
1682 .unwrap();
1683
1684 table
1685 }
1686
1687 #[test]
1688 fn test_evaluate_column() {
1689 let table = create_test_table();
1690 let mut evaluator = ArithmeticEvaluator::new(&table);
1691
1692 let expr = SqlExpression::Column(ColumnRef::unquoted("a".to_string()));
1693 let result = evaluator.evaluate(&expr, 0).unwrap();
1694 assert_eq!(result, DataValue::Integer(10));
1695 }
1696
1697 #[test]
1698 fn test_evaluate_between_column_in_range() {
1699 let table = create_test_table();
1700 let mut evaluator = ArithmeticEvaluator::new(&table);
1701
1702 let expr = SqlExpression::Between {
1704 expr: Box::new(SqlExpression::Column(ColumnRef::unquoted("a".to_string()))),
1705 lower: Box::new(SqlExpression::NumberLiteral("5".to_string())),
1706 upper: Box::new(SqlExpression::NumberLiteral("20".to_string())),
1707 };
1708 assert_eq!(
1709 evaluator.evaluate(&expr, 0).unwrap(),
1710 DataValue::Boolean(true)
1711 );
1712 }
1713
1714 #[test]
1715 fn test_evaluate_between_column_out_of_range() {
1716 let table = create_test_table();
1717 let mut evaluator = ArithmeticEvaluator::new(&table);
1718
1719 let expr = SqlExpression::Between {
1721 expr: Box::new(SqlExpression::Column(ColumnRef::unquoted("a".to_string()))),
1722 lower: Box::new(SqlExpression::NumberLiteral("11".to_string())),
1723 upper: Box::new(SqlExpression::NumberLiteral("20".to_string())),
1724 };
1725 assert_eq!(
1726 evaluator.evaluate(&expr, 0).unwrap(),
1727 DataValue::Boolean(false)
1728 );
1729 }
1730
1731 #[test]
1732 fn test_evaluate_between_endpoints_inclusive() {
1733 let table = create_test_table();
1734 let mut evaluator = ArithmeticEvaluator::new(&table);
1735
1736 let expr = SqlExpression::Between {
1738 expr: Box::new(SqlExpression::Column(ColumnRef::unquoted("a".to_string()))),
1739 lower: Box::new(SqlExpression::NumberLiteral("10".to_string())),
1740 upper: Box::new(SqlExpression::NumberLiteral("10".to_string())),
1741 };
1742 assert_eq!(
1743 evaluator.evaluate(&expr, 0).unwrap(),
1744 DataValue::Boolean(true)
1745 );
1746 }
1747
1748 #[test]
1749 fn test_evaluate_number_literal() {
1750 let table = create_test_table();
1751 let mut evaluator = ArithmeticEvaluator::new(&table);
1752
1753 let expr = SqlExpression::NumberLiteral("42".to_string());
1754 let result = evaluator.evaluate(&expr, 0).unwrap();
1755 assert_eq!(result, DataValue::Integer(42));
1756
1757 let expr = SqlExpression::NumberLiteral("3.14".to_string());
1758 let result = evaluator.evaluate(&expr, 0).unwrap();
1759 assert_eq!(result, DataValue::Float(3.14));
1760 }
1761
1762 #[test]
1763 fn test_add_values() {
1764 let table = create_test_table();
1765 let mut evaluator = ArithmeticEvaluator::new(&table);
1766
1767 let result = evaluator
1769 .add_values(&DataValue::Integer(5), &DataValue::Integer(3))
1770 .unwrap();
1771 assert_eq!(result, DataValue::Integer(8));
1772
1773 let result = evaluator
1775 .add_values(&DataValue::Integer(5), &DataValue::Float(2.5))
1776 .unwrap();
1777 assert_eq!(result, DataValue::Float(7.5));
1778 }
1779
1780 #[test]
1781 fn test_multiply_values() {
1782 let table = create_test_table();
1783 let mut evaluator = ArithmeticEvaluator::new(&table);
1784
1785 let result = evaluator
1787 .multiply_values(&DataValue::Integer(4), &DataValue::Float(2.5))
1788 .unwrap();
1789 assert_eq!(result, DataValue::Float(10.0));
1790 }
1791
1792 #[test]
1793 fn test_divide_values() {
1794 let table = create_test_table();
1795 let mut evaluator = ArithmeticEvaluator::new(&table);
1796
1797 let result = evaluator
1799 .divide_values(&DataValue::Integer(10), &DataValue::Integer(2))
1800 .unwrap();
1801 assert_eq!(result, DataValue::Integer(5));
1802
1803 let result = evaluator
1805 .divide_values(&DataValue::Integer(10), &DataValue::Integer(3))
1806 .unwrap();
1807 assert_eq!(result, DataValue::Float(10.0 / 3.0));
1808 }
1809
1810 #[test]
1811 fn test_division_by_zero() {
1812 let table = create_test_table();
1813 let mut evaluator = ArithmeticEvaluator::new(&table);
1814
1815 let result = evaluator.divide_values(&DataValue::Integer(10), &DataValue::Integer(0));
1816 assert!(result.is_err());
1817 assert!(result.unwrap_err().to_string().contains("Division by zero"));
1818 }
1819
1820 #[test]
1821 fn test_binary_op_expression() {
1822 let table = create_test_table();
1823 let mut evaluator = ArithmeticEvaluator::new(&table);
1824
1825 let expr = SqlExpression::BinaryOp {
1827 left: Box::new(SqlExpression::Column(ColumnRef::unquoted("a".to_string()))),
1828 op: "*".to_string(),
1829 right: Box::new(SqlExpression::Column(ColumnRef::unquoted("b".to_string()))),
1830 };
1831
1832 let result = evaluator.evaluate(&expr, 0).unwrap();
1833 assert_eq!(result, DataValue::Float(25.0));
1834 }
1835}