1use crate::data::arithmetic_evaluator::ArithmeticEvaluator;
2use crate::data::datatable::{DataTable, DataValue};
3use crate::sql::recursive_parser::{Condition, LogicalOp, SqlExpression, WhereClause};
4use anyhow::{anyhow, Result};
5use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
6use tracing::debug;
7
8pub struct RecursiveWhereEvaluator<'a> {
10 table: &'a DataTable,
11 case_insensitive: bool,
12 date_notation: String,
13}
14
15impl<'a> RecursiveWhereEvaluator<'a> {
16 #[must_use]
17 pub fn new(table: &'a DataTable) -> Self {
18 Self {
19 table,
20 case_insensitive: false,
21 date_notation: "us".to_string(),
22 }
23 }
24
25 #[must_use]
26 pub fn with_date_notation(table: &'a DataTable, date_notation: String) -> Self {
27 Self {
28 table,
29 case_insensitive: false,
30 date_notation,
31 }
32 }
33
34 fn parse_datetime_with_notation(&self, s: &str) -> Result<DateTime<Utc>> {
36 if let Ok(parsed_dt) = s.parse::<DateTime<Utc>>() {
38 return Ok(parsed_dt);
39 }
40
41 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") {
43 return Ok(Utc.from_utc_datetime(&dt));
44 }
45 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
46 return Ok(Utc.from_utc_datetime(&dt));
47 }
48 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
49 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
50 }
51
52 if self.date_notation == "european" {
54 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
57 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
58 }
59 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
60 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
61 }
62 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
64 return Ok(Utc.from_utc_datetime(&dt));
65 }
66 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d-%m-%Y %H:%M:%S") {
67 return Ok(Utc.from_utc_datetime(&dt));
68 }
69
70 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
73 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
74 }
75 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
76 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
77 }
78 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
80 return Ok(Utc.from_utc_datetime(&dt));
81 }
82 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m-%d-%Y %H:%M:%S") {
83 return Ok(Utc.from_utc_datetime(&dt));
84 }
85 } else {
86 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
89 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
90 }
91 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
92 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
93 }
94 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
96 return Ok(Utc.from_utc_datetime(&dt));
97 }
98 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m-%d-%Y %H:%M:%S") {
99 return Ok(Utc.from_utc_datetime(&dt));
100 }
101
102 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
105 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
106 }
107 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
108 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
109 }
110 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
112 return Ok(Utc.from_utc_datetime(&dt));
113 }
114 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d-%m-%Y %H:%M:%S") {
115 return Ok(Utc.from_utc_datetime(&dt));
116 }
117 }
118
119 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
121 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
122 }
123
124 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
126 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
127 }
128 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
129 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
130 }
131
132 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y/%m/%d %H:%M:%S") {
134 return Ok(Utc.from_utc_datetime(&dt));
135 }
136
137 Err(anyhow!(
138 "Could not parse date/datetime: '{}'. Supported formats include: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY (based on config), with optional HH:MM:SS",
139 s
140 ))
141 }
142
143 fn find_similar_column(&self, name: &str) -> Option<String> {
145 let columns = self.table.column_names();
146 let mut best_match: Option<(String, usize)> = None;
147
148 for col in columns {
149 let distance = self.edit_distance(&col.to_lowercase(), &name.to_lowercase());
150 let max_distance = if name.len() > 10 { 3 } else { 2 };
153 if distance <= max_distance {
154 match &best_match {
155 None => best_match = Some((col, distance)),
156 Some((_, best_dist)) if distance < *best_dist => {
157 best_match = Some((col, distance));
158 }
159 _ => {}
160 }
161 }
162 }
163
164 best_match.map(|(name, _)| name)
165 }
166
167 fn edit_distance(&self, s1: &str, s2: &str) -> usize {
169 let len1 = s1.len();
170 let len2 = s2.len();
171 let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];
172
173 for i in 0..=len1 {
174 matrix[i][0] = i;
175 }
176 for j in 0..=len2 {
177 matrix[0][j] = j;
178 }
179
180 for (i, c1) in s1.chars().enumerate() {
181 for (j, c2) in s2.chars().enumerate() {
182 let cost = usize::from(c1 != c2);
183 matrix[i + 1][j + 1] = std::cmp::min(
184 matrix[i][j + 1] + 1, std::cmp::min(
186 matrix[i + 1][j] + 1, matrix[i][j] + cost, ),
189 );
190 }
191 }
192
193 matrix[len1][len2]
194 }
195
196 #[must_use]
197 pub fn with_case_insensitive(table: &'a DataTable, case_insensitive: bool) -> Self {
198 Self {
199 table,
200 case_insensitive,
201 date_notation: "us".to_string(),
202 }
203 }
204
205 #[must_use]
206 pub fn with_config(
207 table: &'a DataTable,
208 case_insensitive: bool,
209 date_notation: String,
210 ) -> Self {
211 Self {
212 table,
213 case_insensitive,
214 date_notation,
215 }
216 }
217
218 fn compare_datetime(op: &str, left: &DateTime<Utc>, right: &DateTime<Utc>) -> bool {
220 match op {
221 "=" => left == right,
222 "!=" | "<>" => left != right,
223 ">" => left > right,
224 ">=" => left >= right,
225 "<" => left < right,
226 "<=" => left <= right,
227 _ => false,
228 }
229 }
230
231 fn evaluate_length(
233 &self,
234 object: &str,
235 row_index: usize,
236 ) -> Result<(Option<DataValue>, String)> {
237 let col_index = self.table.get_column_index(object).ok_or_else(|| {
238 let suggestion = self.find_similar_column(object);
239 match suggestion {
240 Some(similar) => {
241 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
242 }
243 None => anyhow!("Column '{}' not found", object),
244 }
245 })?;
246
247 let value = self.table.get_value(row_index, col_index);
248 let length_value = match value {
249 Some(DataValue::String(s)) => Some(DataValue::Integer(s.len() as i64)),
250 Some(DataValue::InternedString(s)) => Some(DataValue::Integer(s.len() as i64)),
251 Some(DataValue::Integer(n)) => Some(DataValue::Integer(n.to_string().len() as i64)),
252 Some(DataValue::Float(f)) => Some(DataValue::Integer(f.to_string().len() as i64)),
253 _ => Some(DataValue::Integer(0)),
254 };
255 Ok((length_value, format!("{object}.Length()")))
256 }
257
258 fn evaluate_indexof(
260 &self,
261 object: &str,
262 search_str: &str,
263 row_index: usize,
264 ) -> Result<(Option<DataValue>, String)> {
265 let col_index = self.table.get_column_index(object).ok_or_else(|| {
266 let suggestion = self.find_similar_column(object);
267 match suggestion {
268 Some(similar) => {
269 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
270 }
271 None => anyhow!("Column '{}' not found", object),
272 }
273 })?;
274
275 let value = self.table.get_value(row_index, col_index);
276 let index_value = match value {
277 Some(DataValue::String(s)) => {
278 let pos = s
280 .to_lowercase()
281 .find(&search_str.to_lowercase())
282 .map_or(-1, |idx| idx as i64);
283 Some(DataValue::Integer(pos))
284 }
285 Some(DataValue::InternedString(s)) => {
286 let pos = s
287 .to_lowercase()
288 .find(&search_str.to_lowercase())
289 .map_or(-1, |idx| idx as i64);
290 Some(DataValue::Integer(pos))
291 }
292 Some(DataValue::Integer(n)) => {
293 let str_val = n.to_string();
294 let pos = str_val.find(search_str).map_or(-1, |idx| idx as i64);
295 Some(DataValue::Integer(pos))
296 }
297 Some(DataValue::Float(f)) => {
298 let str_val = f.to_string();
299 let pos = str_val.find(search_str).map_or(-1, |idx| idx as i64);
300 Some(DataValue::Integer(pos))
301 }
302 _ => Some(DataValue::Integer(-1)), };
304
305 if row_index < 3 {
306 debug!(
307 "RecursiveWhereEvaluator: Row {} IndexOf('{}') = {:?}",
308 row_index, search_str, index_value
309 );
310 }
311 Ok((index_value, format!("{object}.IndexOf('{search_str}')")))
312 }
313
314 fn apply_trim<'b>(s: &'b str, trim_type: &str) -> &'b str {
316 match trim_type {
317 "trim" => s.trim(),
318 "trimstart" => s.trim_start(),
319 "trimend" => s.trim_end(),
320 _ => s,
321 }
322 }
323
324 fn evaluate_trim(
326 &self,
327 object: &str,
328 row_index: usize,
329 trim_type: &str,
330 ) -> Result<(Option<DataValue>, String)> {
331 let col_index = self.table.get_column_index(object).ok_or_else(|| {
332 let suggestion = self.find_similar_column(object);
333 match suggestion {
334 Some(similar) => {
335 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
336 }
337 None => anyhow!("Column '{}' not found", object),
338 }
339 })?;
340
341 let value = self.table.get_value(row_index, col_index);
342 let trimmed_value = match value {
343 Some(DataValue::String(s)) => Some(DataValue::String(
344 Self::apply_trim(s, trim_type).to_string(),
345 )),
346 Some(DataValue::InternedString(s)) => Some(DataValue::String(
347 Self::apply_trim(s, trim_type).to_string(),
348 )),
349 Some(DataValue::Integer(n)) => {
350 let str_val = n.to_string();
351 Some(DataValue::String(
352 Self::apply_trim(&str_val, trim_type).to_string(),
353 ))
354 }
355 Some(DataValue::Float(f)) => {
356 let str_val = f.to_string();
357 Some(DataValue::String(
358 Self::apply_trim(&str_val, trim_type).to_string(),
359 ))
360 }
361 _ => Some(DataValue::String(String::new())),
362 };
363
364 let method_name = match trim_type {
365 "trim" => "Trim",
366 "trimstart" => "TrimStart",
367 "trimend" => "TrimEnd",
368 _ => "Trim",
369 };
370 Ok((trimmed_value, format!("{object}.{method_name}()")))
371 }
372
373 pub fn evaluate(&self, where_clause: &WhereClause, row_index: usize) -> Result<bool> {
375 if row_index < 3 {
377 debug!(
378 "RecursiveWhereEvaluator: evaluate() ENTRY - row {}, {} conditions, case_insensitive={}",
379 row_index,
380 where_clause.conditions.len(),
381 self.case_insensitive
382 );
383 }
384
385 if where_clause.conditions.is_empty() {
386 if row_index < 3 {
387 debug!("RecursiveWhereEvaluator: evaluate() EXIT - no conditions, returning true");
388 }
389 return Ok(true);
390 }
391
392 if row_index < 3 {
394 debug!(
395 "RecursiveWhereEvaluator: evaluate() - evaluating first condition for row {}",
396 row_index
397 );
398 }
399 let mut result = self.evaluate_condition(&where_clause.conditions[0], row_index)?;
400
401 for i in 1..where_clause.conditions.len() {
403 let next_result = self.evaluate_condition(&where_clause.conditions[i], row_index)?;
404
405 if let Some(connector) = &where_clause.conditions[i - 1].connector {
407 result = match connector {
408 LogicalOp::And => result && next_result,
409 LogicalOp::Or => result || next_result,
410 };
411 }
412 }
413
414 Ok(result)
415 }
416
417 fn evaluate_condition(&self, condition: &Condition, row_index: usize) -> Result<bool> {
418 if row_index < 3 {
420 debug!(
421 "RecursiveWhereEvaluator: evaluate_condition() ENTRY - row {}",
422 row_index
423 );
424 }
425 let result = self.evaluate_expression(&condition.expr, row_index);
426 if row_index < 3 {
427 debug!(
428 "RecursiveWhereEvaluator: evaluate_condition() EXIT - row {}, result = {:?}",
429 row_index, result
430 );
431 }
432 result
433 }
434
435 fn evaluate_expression(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
436 if row_index < 3 {
438 debug!(
439 "RecursiveWhereEvaluator: evaluate_expression() ENTRY - row {}, expr = {:?}",
440 row_index, expr
441 );
442 }
443
444 let result = match expr {
445 SqlExpression::BinaryOp { left, op, right } => {
446 self.evaluate_binary_op(left, op, right, row_index)
447 }
448 SqlExpression::InList { expr, values } => {
449 self.evaluate_in_list(expr, values, row_index, false)
450 }
451 SqlExpression::NotInList { expr, values } => {
452 let in_result = self.evaluate_in_list(expr, values, row_index, false)?;
453 Ok(!in_result)
454 }
455 SqlExpression::Between { expr, lower, upper } => {
456 self.evaluate_between(expr, lower, upper, row_index)
457 }
458 SqlExpression::Not { expr } => {
459 let inner_result = self.evaluate_expression(expr, row_index)?;
460 Ok(!inner_result)
461 }
462 SqlExpression::MethodCall {
463 object,
464 method,
465 args,
466 } => {
467 if row_index < 3 {
468 debug!("RecursiveWhereEvaluator: evaluate_expression() - found MethodCall, delegating to evaluate_method_call");
469 }
470 self.evaluate_method_call(object, method, args, row_index)
471 }
472 SqlExpression::CaseExpression {
473 when_branches,
474 else_branch,
475 } => {
476 if row_index < 3 {
477 debug!("RecursiveWhereEvaluator: evaluate_expression() - found CaseExpression, evaluating");
478 }
479 self.evaluate_case_expression_as_bool(when_branches, else_branch, row_index)
480 }
481 _ => {
482 if row_index < 3 {
483 debug!("RecursiveWhereEvaluator: evaluate_expression() - unsupported expression type, returning false");
484 }
485 Ok(false) }
487 };
488
489 if row_index < 3 {
490 debug!(
491 "RecursiveWhereEvaluator: evaluate_expression() EXIT - row {}, result = {:?}",
492 row_index, result
493 );
494 }
495 result
496 }
497
498 fn evaluate_binary_op(
499 &self,
500 left: &SqlExpression,
501 op: &str,
502 right: &SqlExpression,
503 row_index: usize,
504 ) -> Result<bool> {
505 if row_index < 3 {
507 debug!(
508 "RecursiveWhereEvaluator: evaluate_binary_op() ENTRY - row {}, op = '{}'",
509 row_index, op
510 );
511 }
512
513 let (cell_value, column_name) = match left {
515 SqlExpression::MethodCall {
516 object,
517 method,
518 args,
519 } => {
520 match method.to_lowercase().as_str() {
522 "length" => {
523 if !args.is_empty() {
524 return Err(anyhow::anyhow!("Length() takes no arguments"));
525 }
526 self.evaluate_length(object, row_index)?
527 }
528 "indexof" => {
529 if args.len() != 1 {
530 return Err(anyhow::anyhow!("IndexOf() requires exactly 1 argument"));
531 }
532 let search_str = self.extract_string_value(&args[0])?;
533 self.evaluate_indexof(object, &search_str, row_index)?
534 }
535 "trim" => {
536 if !args.is_empty() {
537 return Err(anyhow::anyhow!("Trim() takes no arguments"));
538 }
539 self.evaluate_trim(object, row_index, "trim")?
540 }
541 "trimstart" => {
542 if !args.is_empty() {
543 return Err(anyhow::anyhow!("TrimStart() takes no arguments"));
544 }
545 self.evaluate_trim(object, row_index, "trimstart")?
546 }
547 "trimend" => {
548 if !args.is_empty() {
549 return Err(anyhow::anyhow!("TrimEnd() takes no arguments"));
550 }
551 self.evaluate_trim(object, row_index, "trimend")?
552 }
553 _ => {
554 return Err(anyhow::anyhow!(
555 "Method '{}' cannot be used in comparisons",
556 method
557 ));
558 }
559 }
560 }
561 SqlExpression::BinaryOp {
562 left: _expr_left,
563 op: arith_op,
564 right: _expr_right,
565 } if matches!(arith_op.as_str(), "+" | "-" | "*" | "/") => {
566 let mut evaluator =
568 ArithmeticEvaluator::with_date_notation(self.table, self.date_notation.clone());
569 let computed_value = evaluator.evaluate(left, row_index)?;
570 if row_index < 3 {
571 debug!(
572 "RecursiveWhereEvaluator: evaluate_binary_op() - computed arithmetic expression = {:?}",
573 computed_value
574 );
575 }
576 (Some(computed_value), "computed_expression".to_string())
577 }
578 SqlExpression::FunctionCall { name, .. } => {
579 let mut evaluator =
581 ArithmeticEvaluator::with_date_notation(self.table, self.date_notation.clone());
582 let computed_value = evaluator.evaluate(left, row_index)?;
583 if row_index < 3 {
584 debug!(
585 "RecursiveWhereEvaluator: evaluate_binary_op() - computed function {} = {:?}",
586 name, computed_value
587 );
588 }
589 (Some(computed_value), format!("{name}()"))
590 }
591 _ => {
592 let column_name = self.extract_column_name(left)?;
594 if row_index < 3 {
595 debug!(
596 "RecursiveWhereEvaluator: evaluate_binary_op() - column_name = '{}'",
597 column_name
598 );
599 }
600
601 let col_index = self.table.get_column_index(&column_name).ok_or_else(|| {
602 let suggestion = self.find_similar_column(&column_name);
603 match suggestion {
604 Some(similar) => anyhow!(
605 "Column '{}' not found. Did you mean '{}'?",
606 column_name,
607 similar
608 ),
609 None => anyhow!("Column '{}' not found", column_name),
610 }
611 })?;
612
613 let cell_value = self.table.get_value(row_index, col_index).cloned();
614 (cell_value, column_name)
615 }
616 };
617
618 if row_index < 3 {
619 debug!(
620 "RecursiveWhereEvaluator: evaluate_binary_op() - row {} column '{}' value = {:?}",
621 row_index, column_name, cell_value
622 );
623 }
624
625 let compare_value = self.extract_value(right)?;
627
628 match (cell_value, op.to_uppercase().as_str(), &compare_value) {
630 (Some(DataValue::String(ref a)), "=", ExprValue::String(b)) => {
631 if let (Ok(date_a), Ok(date_b)) = (
633 self.parse_datetime_with_notation(a),
634 self.parse_datetime_with_notation(b),
635 ) {
636 if row_index < 3 {
637 debug!(
638 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' = '{}' = {}",
639 date_a.format("%Y-%m-%d %H:%M:%S"),
640 date_b.format("%Y-%m-%d %H:%M:%S"),
641 date_a == date_b
642 );
643 }
644 Ok(date_a == date_b)
645 } else {
646 if row_index < 3 {
647 debug!(
648 "RecursiveWhereEvaluator: String comparison '{}' = '{}' (case_insensitive={})",
649 a, b, self.case_insensitive
650 );
651 }
652 if self.case_insensitive {
653 Ok(a.to_lowercase() == b.to_lowercase())
654 } else {
655 Ok(a == b)
656 }
657 }
658 }
659 (Some(DataValue::InternedString(ref a)), "=", ExprValue::String(b)) => {
660 if let (Ok(date_a), Ok(date_b)) = (
662 self.parse_datetime_with_notation(a.as_ref()),
663 self.parse_datetime_with_notation(b),
664 ) {
665 if row_index < 3 {
666 debug!(
667 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' = '{}' = {}",
668 date_a.format("%Y-%m-%d %H:%M:%S"),
669 date_b.format("%Y-%m-%d %H:%M:%S"),
670 date_a == date_b
671 );
672 }
673 Ok(date_a == date_b)
674 } else {
675 if row_index < 3 {
676 debug!(
677 "RecursiveWhereEvaluator: InternedString comparison '{}' = '{}' (case_insensitive={})",
678 a, b, self.case_insensitive
679 );
680 }
681 if self.case_insensitive {
682 Ok(a.to_lowercase() == b.to_lowercase())
683 } else {
684 Ok(a.as_ref() == b)
685 }
686 }
687 }
688 (Some(DataValue::String(ref a)), "!=" | "<>", ExprValue::String(b)) => {
689 if let (Ok(date_a), Ok(date_b)) = (
691 self.parse_datetime_with_notation(a),
692 self.parse_datetime_with_notation(b),
693 ) {
694 if row_index < 3 {
695 debug!(
696 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' != '{}' = {}",
697 date_a.format("%Y-%m-%d %H:%M:%S"),
698 date_b.format("%Y-%m-%d %H:%M:%S"),
699 date_a != date_b
700 );
701 }
702 Ok(date_a != date_b)
703 } else {
704 if row_index < 3 {
705 debug!(
706 "RecursiveWhereEvaluator: String comparison '{}' != '{}' (case_insensitive={})",
707 a, b, self.case_insensitive
708 );
709 }
710 if self.case_insensitive {
711 Ok(a.to_lowercase() != b.to_lowercase())
712 } else {
713 Ok(a != b)
714 }
715 }
716 }
717 (Some(DataValue::InternedString(ref a)), "!=" | "<>", ExprValue::String(b)) => {
718 if let (Ok(date_a), Ok(date_b)) = (
720 self.parse_datetime_with_notation(a.as_ref()),
721 self.parse_datetime_with_notation(b),
722 ) {
723 if row_index < 3 {
724 debug!(
725 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' != '{}' = {}",
726 date_a.format("%Y-%m-%d %H:%M:%S"),
727 date_b.format("%Y-%m-%d %H:%M:%S"),
728 date_a != date_b
729 );
730 }
731 Ok(date_a != date_b)
732 } else {
733 if row_index < 3 {
734 debug!(
735 "RecursiveWhereEvaluator: InternedString comparison '{}' != '{}' (case_insensitive={})",
736 a, b, self.case_insensitive
737 );
738 }
739 if self.case_insensitive {
740 Ok(a.to_lowercase() != b.to_lowercase())
741 } else {
742 Ok(a.as_ref() != b)
743 }
744 }
745 }
746 (Some(DataValue::String(ref a)), ">", ExprValue::String(b)) => {
747 if let (Ok(date_a), Ok(date_b)) = (
749 self.parse_datetime_with_notation(a),
750 self.parse_datetime_with_notation(b),
751 ) {
752 if row_index < 3 {
753 debug!(
754 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' > '{}' = {}",
755 date_a.format("%Y-%m-%d %H:%M:%S"),
756 date_b.format("%Y-%m-%d %H:%M:%S"),
757 date_a > date_b
758 );
759 }
760 Ok(date_a > date_b)
761 } else if self.case_insensitive {
762 Ok(a.to_lowercase() > b.to_lowercase())
763 } else {
764 Ok(a > b)
765 }
766 }
767 (Some(DataValue::InternedString(ref a)), ">", ExprValue::String(b)) => {
768 if let (Ok(date_a), Ok(date_b)) = (
770 self.parse_datetime_with_notation(a.as_ref()),
771 self.parse_datetime_with_notation(b),
772 ) {
773 if row_index < 3 {
774 debug!(
775 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' > '{}' = {}",
776 date_a.format("%Y-%m-%d %H:%M:%S"),
777 date_b.format("%Y-%m-%d %H:%M:%S"),
778 date_a > date_b
779 );
780 }
781 Ok(date_a > date_b)
782 } else if self.case_insensitive {
783 Ok(a.to_lowercase() > b.to_lowercase())
784 } else {
785 Ok(a.as_ref() > b)
786 }
787 }
788 (Some(DataValue::String(ref a)), ">=", ExprValue::String(b)) => {
789 if let (Ok(date_a), Ok(date_b)) = (
791 self.parse_datetime_with_notation(a),
792 self.parse_datetime_with_notation(b),
793 ) {
794 if row_index < 3 {
795 debug!(
796 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' >= '{}' = {}",
797 date_a.format("%Y-%m-%d %H:%M:%S"),
798 date_b.format("%Y-%m-%d %H:%M:%S"),
799 date_a >= date_b
800 );
801 }
802 Ok(date_a >= date_b)
803 } else if self.case_insensitive {
804 Ok(a.to_lowercase() >= b.to_lowercase())
805 } else {
806 Ok(a >= b)
807 }
808 }
809 (Some(DataValue::InternedString(ref a)), ">=", ExprValue::String(b)) => {
810 if let (Ok(date_a), Ok(date_b)) = (
812 self.parse_datetime_with_notation(a.as_ref()),
813 self.parse_datetime_with_notation(b),
814 ) {
815 if row_index < 3 {
816 debug!(
817 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' >= '{}' = {}",
818 date_a.format("%Y-%m-%d %H:%M:%S"),
819 date_b.format("%Y-%m-%d %H:%M:%S"),
820 date_a >= date_b
821 );
822 }
823 Ok(date_a >= date_b)
824 } else if self.case_insensitive {
825 Ok(a.to_lowercase() >= b.to_lowercase())
826 } else {
827 Ok(a.as_ref() >= b)
828 }
829 }
830 (Some(DataValue::String(ref a)), "<", ExprValue::String(b)) => {
831 if let (Ok(date_a), Ok(date_b)) = (
833 self.parse_datetime_with_notation(a),
834 self.parse_datetime_with_notation(b),
835 ) {
836 if row_index < 3 {
837 debug!(
838 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' < '{}' = {}",
839 date_a.format("%Y-%m-%d %H:%M:%S"),
840 date_b.format("%Y-%m-%d %H:%M:%S"),
841 date_a < date_b
842 );
843 }
844 Ok(date_a < date_b)
845 } else if self.case_insensitive {
846 Ok(a.to_lowercase() < b.to_lowercase())
847 } else {
848 Ok(a < b)
849 }
850 }
851 (Some(DataValue::InternedString(ref a)), "<", ExprValue::String(b)) => {
852 if let (Ok(date_a), Ok(date_b)) = (
854 self.parse_datetime_with_notation(a.as_ref()),
855 self.parse_datetime_with_notation(b),
856 ) {
857 if row_index < 3 {
858 debug!(
859 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' < '{}' = {}",
860 date_a.format("%Y-%m-%d %H:%M:%S"),
861 date_b.format("%Y-%m-%d %H:%M:%S"),
862 date_a < date_b
863 );
864 }
865 Ok(date_a < date_b)
866 } else if self.case_insensitive {
867 Ok(a.to_lowercase() < b.to_lowercase())
868 } else {
869 Ok(a.as_ref() < b)
870 }
871 }
872 (Some(DataValue::String(ref a)), "<=", ExprValue::String(b)) => {
873 if let (Ok(date_a), Ok(date_b)) = (
875 self.parse_datetime_with_notation(a),
876 self.parse_datetime_with_notation(b),
877 ) {
878 if row_index < 3 {
879 debug!(
880 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' <= '{}' = {}",
881 date_a.format("%Y-%m-%d %H:%M:%S"),
882 date_b.format("%Y-%m-%d %H:%M:%S"),
883 date_a <= date_b
884 );
885 }
886 Ok(date_a <= date_b)
887 } else if self.case_insensitive {
888 Ok(a.to_lowercase() <= b.to_lowercase())
889 } else {
890 Ok(a <= b)
891 }
892 }
893 (Some(DataValue::InternedString(ref a)), "<=", ExprValue::String(b)) => {
894 if let (Ok(date_a), Ok(date_b)) = (
896 self.parse_datetime_with_notation(a.as_ref()),
897 self.parse_datetime_with_notation(b),
898 ) {
899 if row_index < 3 {
900 debug!(
901 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' <= '{}' = {}",
902 date_a.format("%Y-%m-%d %H:%M:%S"),
903 date_b.format("%Y-%m-%d %H:%M:%S"),
904 date_a <= date_b
905 );
906 }
907 Ok(date_a <= date_b)
908 } else if self.case_insensitive {
909 Ok(a.to_lowercase() <= b.to_lowercase())
910 } else {
911 Ok(a.as_ref() <= b)
912 }
913 }
914
915 (Some(DataValue::Integer(a)), "=", ExprValue::Number(b)) => Ok(a as f64 == *b),
916 (Some(DataValue::Integer(a)), "!=" | "<>", ExprValue::Number(b)) => Ok(a as f64 != *b),
917 (Some(DataValue::Integer(a)), ">", ExprValue::Number(b)) => Ok(a as f64 > *b),
918 (Some(DataValue::Integer(a)), ">=", ExprValue::Number(b)) => Ok(a as f64 >= *b),
919 (Some(DataValue::Integer(a)), "<", ExprValue::Number(b)) => Ok((a as f64) < *b),
920 (Some(DataValue::Integer(a)), "<=", ExprValue::Number(b)) => Ok(a as f64 <= *b),
921
922 (Some(DataValue::Float(a)), "=", ExprValue::Number(b)) => {
923 Ok((a - b).abs() < f64::EPSILON)
924 }
925 (Some(DataValue::Float(a)), "!=" | "<>", ExprValue::Number(b)) => {
926 Ok((a - b).abs() >= f64::EPSILON)
927 }
928 (Some(DataValue::Float(a)), ">", ExprValue::Number(b)) => Ok(a > *b),
929 (Some(DataValue::Float(a)), ">=", ExprValue::Number(b)) => Ok(a >= *b),
930 (Some(DataValue::Float(a)), "<", ExprValue::Number(b)) => Ok(a < *b),
931 (Some(DataValue::Float(a)), "<=", ExprValue::Number(b)) => Ok(a <= *b),
932
933 (Some(DataValue::Boolean(a)), "=", ExprValue::Boolean(b)) => Ok(a == *b),
935 (Some(DataValue::Boolean(a)), "!=" | "<>", ExprValue::Boolean(b)) => Ok(a != *b),
936
937 (Some(DataValue::Boolean(a)), "=", ExprValue::String(b)) => {
939 let bool_str = a.to_string();
940 if self.case_insensitive {
941 Ok(bool_str.to_lowercase() == b.to_lowercase())
942 } else {
943 Ok(bool_str == *b)
944 }
945 }
946 (Some(DataValue::Boolean(a)), "!=" | "<>", ExprValue::String(b)) => {
947 let bool_str = a.to_string();
948 if self.case_insensitive {
949 Ok(bool_str.to_lowercase() != b.to_lowercase())
950 } else {
951 Ok(bool_str != *b)
952 }
953 }
954
955 (Some(DataValue::String(ref text)), "LIKE", ExprValue::String(pattern)) => {
957 let regex_pattern = pattern.replace('%', ".*").replace('_', ".");
958 let regex = regex::RegexBuilder::new(&format!("^{regex_pattern}$"))
959 .case_insensitive(true)
960 .build()
961 .map_err(|e| anyhow::anyhow!("Invalid LIKE pattern: {}", e))?;
962 Ok(regex.is_match(text))
963 }
964 (Some(DataValue::InternedString(ref text)), "LIKE", ExprValue::String(pattern)) => {
965 let regex_pattern = pattern.replace('%', ".*").replace('_', ".");
966 let regex = regex::RegexBuilder::new(&format!("^{regex_pattern}$"))
967 .case_insensitive(true)
968 .build()
969 .map_err(|e| anyhow::anyhow!("Invalid LIKE pattern: {}", e))?;
970 Ok(regex.is_match(text.as_ref()))
971 }
972
973 (None | Some(DataValue::Null), "IS", ExprValue::Null) => Ok(true),
975 (Some(_), "IS", ExprValue::Null) => Ok(false),
976 (None | Some(DataValue::Null), "IS NOT", ExprValue::Null) => Ok(false),
977 (Some(_), "IS NOT", ExprValue::Null) => Ok(true),
978
979 (Some(DataValue::String(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
981 if row_index < 3 {
982 debug!(
983 "RecursiveWhereEvaluator: DateTime comparison '{}' {} '{}' - attempting parse",
984 date_str,
985 op_str,
986 dt.format("%Y-%m-%d %H:%M:%S")
987 );
988 }
989
990 if let Ok(parsed_dt) = self.parse_datetime_with_notation(date_str) {
992 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
993 if row_index < 3 {
994 debug!(
995 "RecursiveWhereEvaluator: DateTime parsed successfully: '{}' {} '{}' = {}",
996 parsed_dt.format("%Y-%m-%d %H:%M:%S"),
997 op_str,
998 dt.format("%Y-%m-%d %H:%M:%S"),
999 result
1000 );
1001 }
1002 Ok(result)
1003 } else {
1004 if row_index < 3 {
1005 debug!(
1006 "RecursiveWhereEvaluator: DateTime parse FAILED for '{}' - no matching format",
1007 date_str
1008 );
1009 }
1010 Ok(false)
1011 }
1012 }
1013 (Some(DataValue::InternedString(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
1014 if row_index < 3 {
1015 debug!(
1016 "RecursiveWhereEvaluator: DateTime comparison (interned) '{}' {} '{}' - attempting parse",
1017 date_str,
1018 op_str,
1019 dt.format("%Y-%m-%d %H:%M:%S")
1020 );
1021 }
1022
1023 if let Ok(parsed_dt) = self.parse_datetime_with_notation(date_str.as_ref()) {
1025 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
1026 if row_index < 3 {
1027 debug!(
1028 "RecursiveWhereEvaluator: DateTime parsed successfully: '{}' {} '{}' = {}",
1029 parsed_dt.format("%Y-%m-%d %H:%M:%S"),
1030 op_str,
1031 dt.format("%Y-%m-%d %H:%M:%S"),
1032 result
1033 );
1034 }
1035 Ok(result)
1036 } else {
1037 if row_index < 3 {
1038 debug!(
1039 "RecursiveWhereEvaluator: DateTime parse FAILED for '{}' - no matching format",
1040 date_str
1041 );
1042 }
1043 Ok(false)
1044 }
1045 }
1046
1047 (Some(DataValue::DateTime(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
1049 if row_index < 3 {
1050 debug!(
1051 "RecursiveWhereEvaluator: DateTime vs DateTime comparison '{}' {} '{}' - direct comparison",
1052 date_str, op_str, dt.format("%Y-%m-%d %H:%M:%S")
1053 );
1054 }
1055
1056 if let Ok(parsed_dt) = self.parse_datetime_with_notation(date_str) {
1058 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
1059 if row_index < 3 {
1060 debug!(
1061 "RecursiveWhereEvaluator: DateTime vs DateTime parsed successfully: '{}' {} '{}' = {}",
1062 parsed_dt.format("%Y-%m-%d %H:%M:%S"), op_str, dt.format("%Y-%m-%d %H:%M:%S"), result
1063 );
1064 }
1065 Ok(result)
1066 } else {
1067 if row_index < 3 {
1068 debug!(
1069 "RecursiveWhereEvaluator: DateTime vs DateTime parse FAILED for '{}' - no matching format",
1070 date_str
1071 );
1072 }
1073 Ok(false)
1074 }
1075 }
1076
1077 _ => Ok(false),
1078 }
1079 }
1080
1081 fn evaluate_in_list(
1082 &self,
1083 expr: &SqlExpression,
1084 values: &[SqlExpression],
1085 row_index: usize,
1086 _ignore_case: bool,
1087 ) -> Result<bool> {
1088 let column_name = self.extract_column_name(expr)?;
1089 let col_index = self
1090 .table
1091 .get_column_index(&column_name)
1092 .ok_or_else(|| anyhow::anyhow!("Column '{}' not found", column_name))?;
1093
1094 let cell_value = self.table.get_value(row_index, col_index).cloned();
1095
1096 for value_expr in values {
1097 let compare_value = self.extract_value(value_expr)?;
1098 let matches = match (cell_value.as_ref(), &compare_value) {
1099 (Some(DataValue::String(a)), ExprValue::String(b)) => {
1100 if self.case_insensitive {
1101 if row_index < 3 {
1102 debug!("RecursiveWhereEvaluator: IN list string comparison '{}' in '{}' (case_insensitive={})", a, b, self.case_insensitive);
1103 }
1104 a.to_lowercase() == b.to_lowercase()
1105 } else {
1106 a == b
1107 }
1108 }
1109 (Some(DataValue::InternedString(a)), ExprValue::String(b)) => {
1110 if self.case_insensitive {
1111 if row_index < 3 {
1112 debug!("RecursiveWhereEvaluator: IN list interned string comparison '{}' in '{}' (case_insensitive={})", a, b, self.case_insensitive);
1113 }
1114 a.to_lowercase() == b.to_lowercase()
1115 } else {
1116 a.as_ref() == b
1117 }
1118 }
1119 (Some(DataValue::Integer(a)), ExprValue::Number(b)) => *a as f64 == *b,
1120 (Some(DataValue::Float(a)), ExprValue::Number(b)) => (*a - b).abs() < f64::EPSILON,
1121 _ => false,
1122 };
1123
1124 if matches {
1125 return Ok(true);
1126 }
1127 }
1128
1129 Ok(false)
1130 }
1131
1132 fn evaluate_between(
1133 &self,
1134 expr: &SqlExpression,
1135 lower: &SqlExpression,
1136 upper: &SqlExpression,
1137 row_index: usize,
1138 ) -> Result<bool> {
1139 let column_name = self.extract_column_name(expr)?;
1140 let col_index = self
1141 .table
1142 .get_column_index(&column_name)
1143 .ok_or_else(|| anyhow::anyhow!("Column '{}' not found", column_name))?;
1144
1145 let cell_value = self.table.get_value(row_index, col_index).cloned();
1146 let lower_value = self.extract_value(lower)?;
1147 let upper_value = self.extract_value(upper)?;
1148
1149 match (cell_value, &lower_value, &upper_value) {
1150 (Some(DataValue::Integer(n)), ExprValue::Number(l), ExprValue::Number(u)) => {
1151 Ok(n as f64 >= *l && n as f64 <= *u)
1152 }
1153 (Some(DataValue::Float(n)), ExprValue::Number(l), ExprValue::Number(u)) => {
1154 Ok(n >= *l && n <= *u)
1155 }
1156 (Some(DataValue::String(ref s)), ExprValue::String(l), ExprValue::String(u)) => {
1157 Ok(s >= l && s <= u)
1158 }
1159 (
1160 Some(DataValue::InternedString(ref s)),
1161 ExprValue::String(l),
1162 ExprValue::String(u),
1163 ) => Ok(s.as_ref() >= l && s.as_ref() <= u),
1164 _ => Ok(false),
1165 }
1166 }
1167
1168 fn evaluate_method_call(
1169 &self,
1170 object: &str,
1171 method: &str,
1172 args: &[SqlExpression],
1173 row_index: usize,
1174 ) -> Result<bool> {
1175 if row_index < 3 {
1176 debug!(
1177 "RecursiveWhereEvaluator: evaluate_method_call - object='{}', method='{}', row={}",
1178 object, method, row_index
1179 );
1180 }
1181
1182 let col_index = self.table.get_column_index(object).ok_or_else(|| {
1184 let suggestion = self.find_similar_column(object);
1185 match suggestion {
1186 Some(similar) => {
1187 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
1188 }
1189 None => anyhow!("Column '{}' not found", object),
1190 }
1191 })?;
1192
1193 let cell_value = self.table.get_value(row_index, col_index).cloned();
1194 if row_index < 3 {
1195 debug!(
1196 "RecursiveWhereEvaluator: Row {} column '{}' value = {:?}",
1197 row_index, object, cell_value
1198 );
1199 }
1200
1201 match method.to_lowercase().as_str() {
1202 "contains" => {
1203 if args.len() != 1 {
1204 return Err(anyhow::anyhow!("Contains requires exactly 1 argument"));
1205 }
1206 let search_str = self.extract_string_value(&args[0])?;
1207 let search_lower = search_str.to_lowercase();
1209
1210 match cell_value {
1212 Some(DataValue::String(ref s)) => {
1213 let result = s.to_lowercase().contains(&search_lower);
1214 if row_index < 3 {
1216 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on '{}' = {} (case-insensitive)", row_index, search_str, s, result);
1217 }
1218 Ok(result)
1219 }
1220 Some(DataValue::InternedString(ref s)) => {
1221 let result = s.to_lowercase().contains(&search_lower);
1222 if row_index < 3 {
1224 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on interned '{}' = {} (case-insensitive)", row_index, search_str, s, result);
1225 }
1226 Ok(result)
1227 }
1228 Some(DataValue::Integer(n)) => {
1229 let str_val = n.to_string();
1230 let result = str_val.contains(&search_str);
1231 if row_index < 3 {
1232 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on integer '{}' = {}", row_index, search_str, str_val, result);
1233 }
1234 Ok(result)
1235 }
1236 Some(DataValue::Float(f)) => {
1237 let str_val = f.to_string();
1238 let result = str_val.contains(&search_str);
1239 if row_index < 3 {
1240 debug!(
1241 "RecursiveWhereEvaluator: Row {} contains('{}') on float '{}' = {}",
1242 row_index, search_str, str_val, result
1243 );
1244 }
1245 Ok(result)
1246 }
1247 Some(DataValue::Boolean(b)) => {
1248 let str_val = b.to_string();
1249 let result = str_val.contains(&search_str);
1250 if row_index < 3 {
1251 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on boolean '{}' = {}", row_index, search_str, str_val, result);
1252 }
1253 Ok(result)
1254 }
1255 Some(DataValue::DateTime(dt)) => {
1256 let result = dt.contains(&search_str);
1258 if row_index < 3 {
1259 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on datetime '{}' = {}", row_index, search_str, dt, result);
1260 }
1261 Ok(result)
1262 }
1263 _ => {
1264 if row_index < 3 {
1265 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on null/empty value = false", row_index, search_str);
1266 }
1267 Ok(false)
1268 }
1269 }
1270 }
1271 "startswith" => {
1272 if args.len() != 1 {
1273 return Err(anyhow::anyhow!("StartsWith requires exactly 1 argument"));
1274 }
1275 let prefix = self.extract_string_value(&args[0])?;
1276
1277 match cell_value {
1279 Some(DataValue::String(ref s)) => {
1280 Ok(s.to_lowercase().starts_with(&prefix.to_lowercase()))
1281 }
1282 Some(DataValue::InternedString(ref s)) => {
1283 Ok(s.to_lowercase().starts_with(&prefix.to_lowercase()))
1284 }
1285 Some(DataValue::Integer(n)) => Ok(n.to_string().starts_with(&prefix)),
1286 Some(DataValue::Float(f)) => Ok(f.to_string().starts_with(&prefix)),
1287 Some(DataValue::Boolean(b)) => Ok(b.to_string().starts_with(&prefix)),
1288 Some(DataValue::DateTime(dt)) => Ok(dt.starts_with(&prefix)),
1289 _ => Ok(false),
1290 }
1291 }
1292 "endswith" => {
1293 if args.len() != 1 {
1294 return Err(anyhow::anyhow!("EndsWith requires exactly 1 argument"));
1295 }
1296 let suffix = self.extract_string_value(&args[0])?;
1297
1298 match cell_value {
1300 Some(DataValue::String(ref s)) => {
1301 Ok(s.to_lowercase().ends_with(&suffix.to_lowercase()))
1302 }
1303 Some(DataValue::InternedString(ref s)) => {
1304 Ok(s.to_lowercase().ends_with(&suffix.to_lowercase()))
1305 }
1306 Some(DataValue::Integer(n)) => Ok(n.to_string().ends_with(&suffix)),
1307 Some(DataValue::Float(f)) => Ok(f.to_string().ends_with(&suffix)),
1308 Some(DataValue::Boolean(b)) => Ok(b.to_string().ends_with(&suffix)),
1309 Some(DataValue::DateTime(dt)) => Ok(dt.ends_with(&suffix)),
1310 _ => Ok(false),
1311 }
1312 }
1313 _ => Err(anyhow::anyhow!("Unsupported method: {}", method)),
1314 }
1315 }
1316
1317 fn extract_column_name(&self, expr: &SqlExpression) -> Result<String> {
1318 match expr {
1319 SqlExpression::Column(name) => Ok(name.clone()),
1320 _ => Err(anyhow::anyhow!("Expected column name, got: {:?}", expr)),
1321 }
1322 }
1323
1324 fn extract_string_value(&self, expr: &SqlExpression) -> Result<String> {
1325 match expr {
1326 SqlExpression::StringLiteral(s) => Ok(s.clone()),
1327 _ => Err(anyhow::anyhow!("Expected string literal, got: {:?}", expr)),
1328 }
1329 }
1330
1331 fn extract_value(&self, expr: &SqlExpression) -> Result<ExprValue> {
1332 match expr {
1333 SqlExpression::StringLiteral(s) => Ok(ExprValue::String(s.clone())),
1334 SqlExpression::BooleanLiteral(b) => Ok(ExprValue::Boolean(*b)),
1335 SqlExpression::NumberLiteral(n) => {
1336 if let Ok(num) = n.parse::<f64>() {
1337 Ok(ExprValue::Number(num))
1338 } else {
1339 Ok(ExprValue::String(n.clone()))
1340 }
1341 }
1342 SqlExpression::DateTimeConstructor {
1343 year,
1344 month,
1345 day,
1346 hour,
1347 minute,
1348 second,
1349 } => {
1350 let naive_date = NaiveDate::from_ymd_opt(*year, *month, *day)
1352 .ok_or_else(|| anyhow::anyhow!("Invalid date: {}-{}-{}", year, month, day))?;
1353 let naive_time = NaiveTime::from_hms_opt(
1354 hour.unwrap_or(0),
1355 minute.unwrap_or(0),
1356 second.unwrap_or(0),
1357 )
1358 .ok_or_else(|| anyhow::anyhow!("Invalid time"))?;
1359 let naive_datetime = NaiveDateTime::new(naive_date, naive_time);
1360 let datetime = Utc.from_utc_datetime(&naive_datetime);
1361 Ok(ExprValue::DateTime(datetime))
1362 }
1363 SqlExpression::DateTimeToday {
1364 hour,
1365 minute,
1366 second,
1367 } => {
1368 let today = Local::now().date_naive();
1370 let time = NaiveTime::from_hms_opt(
1371 hour.unwrap_or(0),
1372 minute.unwrap_or(0),
1373 second.unwrap_or(0),
1374 )
1375 .ok_or_else(|| anyhow::anyhow!("Invalid time"))?;
1376 let naive_datetime = NaiveDateTime::new(today, time);
1377 let datetime = Utc.from_utc_datetime(&naive_datetime);
1378 Ok(ExprValue::DateTime(datetime))
1379 }
1380 _ => Ok(ExprValue::Null),
1381 }
1382 }
1383
1384 fn evaluate_case_expression_as_bool(
1386 &self,
1387 when_branches: &[crate::sql::recursive_parser::WhenBranch],
1388 else_branch: &Option<Box<SqlExpression>>,
1389 row_index: usize,
1390 ) -> Result<bool> {
1391 debug!(
1392 "RecursiveWhereEvaluator: evaluating CASE expression as bool for row {}",
1393 row_index
1394 );
1395
1396 for branch in when_branches {
1398 let condition_result = self.evaluate_expression(&branch.condition, row_index)?;
1400
1401 if condition_result {
1402 debug!("CASE: WHEN condition matched, evaluating result expression as bool");
1403 return self.evaluate_expression_as_bool(&branch.result, row_index);
1405 }
1406 }
1407
1408 if let Some(else_expr) = else_branch {
1410 debug!("CASE: No WHEN matched, evaluating ELSE expression as bool");
1411 self.evaluate_expression_as_bool(else_expr, row_index)
1412 } else {
1413 debug!("CASE: No WHEN matched and no ELSE, returning false");
1414 Ok(false)
1415 }
1416 }
1417
1418 fn evaluate_expression_as_bool(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
1420 match expr {
1421 SqlExpression::BinaryOp { .. }
1423 | SqlExpression::InList { .. }
1424 | SqlExpression::NotInList { .. }
1425 | SqlExpression::Between { .. }
1426 | SqlExpression::Not { .. }
1427 | SqlExpression::MethodCall { .. } => self.evaluate_expression(expr, row_index),
1428 SqlExpression::CaseExpression {
1430 when_branches,
1431 else_branch,
1432 } => self.evaluate_case_expression_as_bool(when_branches, else_branch, row_index),
1433 _ => {
1435 let mut evaluator =
1437 crate::data::arithmetic_evaluator::ArithmeticEvaluator::with_date_notation(
1438 self.table,
1439 self.date_notation.clone(),
1440 );
1441 let value = evaluator.evaluate(expr, row_index)?;
1442
1443 match value {
1444 crate::data::datatable::DataValue::Boolean(b) => Ok(b),
1445 crate::data::datatable::DataValue::Integer(i) => Ok(i != 0),
1446 crate::data::datatable::DataValue::Float(f) => Ok(f != 0.0),
1447 crate::data::datatable::DataValue::Null => Ok(false),
1448 crate::data::datatable::DataValue::String(s) => Ok(!s.is_empty()),
1449 crate::data::datatable::DataValue::InternedString(s) => Ok(!s.is_empty()),
1450 _ => Ok(true), }
1452 }
1453 }
1454 }
1455}
1456
1457enum ExprValue {
1458 String(String),
1459 Number(f64),
1460 Boolean(bool),
1461 DateTime(DateTime<Utc>),
1462 Null,
1463}