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 pub fn new(table: &'a DataTable) -> Self {
17 Self {
18 table,
19 case_insensitive: false,
20 date_notation: "us".to_string(),
21 }
22 }
23
24 pub fn with_date_notation(table: &'a DataTable, date_notation: String) -> Self {
25 Self {
26 table,
27 case_insensitive: false,
28 date_notation,
29 }
30 }
31
32 fn parse_datetime_with_notation(&self, s: &str) -> Result<DateTime<Utc>> {
34 if let Ok(parsed_dt) = s.parse::<DateTime<Utc>>() {
36 return Ok(parsed_dt);
37 }
38
39 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") {
41 return Ok(Utc.from_utc_datetime(&dt));
42 }
43 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
44 return Ok(Utc.from_utc_datetime(&dt));
45 }
46 if let Ok(dt) = NaiveDate::parse_from_str(s, "%Y-%m-%d") {
47 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
48 }
49
50 if self.date_notation == "european" {
52 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
55 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
56 }
57 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
58 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
59 }
60 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
62 return Ok(Utc.from_utc_datetime(&dt));
63 }
64 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d-%m-%Y %H:%M:%S") {
65 return Ok(Utc.from_utc_datetime(&dt));
66 }
67
68 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
71 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
72 }
73 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
74 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
75 }
76 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
78 return Ok(Utc.from_utc_datetime(&dt));
79 }
80 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m-%d-%Y %H:%M:%S") {
81 return Ok(Utc.from_utc_datetime(&dt));
82 }
83 } else {
84 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m/%d/%Y") {
87 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
88 }
89 if let Ok(dt) = NaiveDate::parse_from_str(s, "%m-%d-%Y") {
90 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
91 }
92 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m/%d/%Y %H:%M:%S") {
94 return Ok(Utc.from_utc_datetime(&dt));
95 }
96 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%m-%d-%Y %H:%M:%S") {
97 return Ok(Utc.from_utc_datetime(&dt));
98 }
99
100 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d/%m/%Y") {
103 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
104 }
105 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%m-%Y") {
106 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
107 }
108 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d/%m/%Y %H:%M:%S") {
110 return Ok(Utc.from_utc_datetime(&dt));
111 }
112 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%d-%m-%Y %H:%M:%S") {
113 return Ok(Utc.from_utc_datetime(&dt));
114 }
115 }
116
117 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d-%b-%Y") {
119 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
120 }
121
122 if let Ok(dt) = NaiveDate::parse_from_str(s, "%B %d, %Y") {
124 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
125 }
126 if let Ok(dt) = NaiveDate::parse_from_str(s, "%d %B %Y") {
127 return Ok(Utc.from_utc_datetime(&dt.and_hms_opt(0, 0, 0).unwrap()));
128 }
129
130 if let Ok(dt) = NaiveDateTime::parse_from_str(s, "%Y/%m/%d %H:%M:%S") {
132 return Ok(Utc.from_utc_datetime(&dt));
133 }
134
135 Err(anyhow!(
136 "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",
137 s
138 ))
139 }
140
141 fn find_similar_column(&self, name: &str) -> Option<String> {
143 let columns = self.table.column_names();
144 let mut best_match: Option<(String, usize)> = None;
145
146 for col in columns {
147 let distance = self.edit_distance(&col.to_lowercase(), &name.to_lowercase());
148 let max_distance = if name.len() > 10 { 3 } else { 2 };
151 if distance <= max_distance {
152 match &best_match {
153 None => best_match = Some((col, distance)),
154 Some((_, best_dist)) if distance < *best_dist => {
155 best_match = Some((col, distance));
156 }
157 _ => {}
158 }
159 }
160 }
161
162 best_match.map(|(name, _)| name)
163 }
164
165 fn edit_distance(&self, s1: &str, s2: &str) -> usize {
167 let len1 = s1.len();
168 let len2 = s2.len();
169 let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];
170
171 for i in 0..=len1 {
172 matrix[i][0] = i;
173 }
174 for j in 0..=len2 {
175 matrix[0][j] = j;
176 }
177
178 for (i, c1) in s1.chars().enumerate() {
179 for (j, c2) in s2.chars().enumerate() {
180 let cost = if c1 == c2 { 0 } else { 1 };
181 matrix[i + 1][j + 1] = std::cmp::min(
182 matrix[i][j + 1] + 1, std::cmp::min(
184 matrix[i + 1][j] + 1, matrix[i][j] + cost, ),
187 );
188 }
189 }
190
191 matrix[len1][len2]
192 }
193
194 pub fn with_case_insensitive(table: &'a DataTable, case_insensitive: bool) -> Self {
195 Self {
196 table,
197 case_insensitive,
198 date_notation: "us".to_string(),
199 }
200 }
201
202 pub fn with_config(
203 table: &'a DataTable,
204 case_insensitive: bool,
205 date_notation: String,
206 ) -> Self {
207 Self {
208 table,
209 case_insensitive,
210 date_notation,
211 }
212 }
213
214 fn compare_datetime(op: &str, left: &DateTime<Utc>, right: &DateTime<Utc>) -> bool {
216 match op {
217 "=" => left == right,
218 "!=" | "<>" => left != right,
219 ">" => left > right,
220 ">=" => left >= right,
221 "<" => left < right,
222 "<=" => left <= right,
223 _ => false,
224 }
225 }
226
227 fn evaluate_length(
229 &self,
230 object: &str,
231 row_index: usize,
232 ) -> Result<(Option<DataValue>, String)> {
233 let col_index = self.table.get_column_index(object).ok_or_else(|| {
234 let suggestion = self.find_similar_column(object);
235 match suggestion {
236 Some(similar) => {
237 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
238 }
239 None => anyhow!("Column '{}' not found", object),
240 }
241 })?;
242
243 let value = self.table.get_value(row_index, col_index);
244 let length_value = match value {
245 Some(DataValue::String(s)) => Some(DataValue::Integer(s.len() as i64)),
246 Some(DataValue::InternedString(s)) => Some(DataValue::Integer(s.len() as i64)),
247 Some(DataValue::Integer(n)) => Some(DataValue::Integer(n.to_string().len() as i64)),
248 Some(DataValue::Float(f)) => Some(DataValue::Integer(f.to_string().len() as i64)),
249 _ => Some(DataValue::Integer(0)),
250 };
251 Ok((length_value, format!("{}.Length()", object)))
252 }
253
254 fn evaluate_indexof(
256 &self,
257 object: &str,
258 search_str: &str,
259 row_index: usize,
260 ) -> Result<(Option<DataValue>, String)> {
261 let col_index = self.table.get_column_index(object).ok_or_else(|| {
262 let suggestion = self.find_similar_column(object);
263 match suggestion {
264 Some(similar) => {
265 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
266 }
267 None => anyhow!("Column '{}' not found", object),
268 }
269 })?;
270
271 let value = self.table.get_value(row_index, col_index);
272 let index_value = match value {
273 Some(DataValue::String(s)) => {
274 let pos = s
276 .to_lowercase()
277 .find(&search_str.to_lowercase())
278 .map(|idx| idx as i64)
279 .unwrap_or(-1);
280 Some(DataValue::Integer(pos))
281 }
282 Some(DataValue::InternedString(s)) => {
283 let pos = s
284 .to_lowercase()
285 .find(&search_str.to_lowercase())
286 .map(|idx| idx as i64)
287 .unwrap_or(-1);
288 Some(DataValue::Integer(pos))
289 }
290 Some(DataValue::Integer(n)) => {
291 let str_val = n.to_string();
292 let pos = str_val.find(search_str).map(|idx| idx as i64).unwrap_or(-1);
293 Some(DataValue::Integer(pos))
294 }
295 Some(DataValue::Float(f)) => {
296 let str_val = f.to_string();
297 let pos = str_val.find(search_str).map(|idx| idx as i64).unwrap_or(-1);
298 Some(DataValue::Integer(pos))
299 }
300 _ => Some(DataValue::Integer(-1)), };
302
303 if row_index < 3 {
304 debug!(
305 "RecursiveWhereEvaluator: Row {} IndexOf('{}') = {:?}",
306 row_index, search_str, index_value
307 );
308 }
309 Ok((index_value, format!("{}.IndexOf('{}')", object, search_str)))
310 }
311
312 fn apply_trim<'b>(s: &'b str, trim_type: &str) -> &'b str {
314 match trim_type {
315 "trim" => s.trim(),
316 "trimstart" => s.trim_start(),
317 "trimend" => s.trim_end(),
318 _ => s,
319 }
320 }
321
322 fn evaluate_trim(
324 &self,
325 object: &str,
326 row_index: usize,
327 trim_type: &str,
328 ) -> Result<(Option<DataValue>, String)> {
329 let col_index = self.table.get_column_index(object).ok_or_else(|| {
330 let suggestion = self.find_similar_column(object);
331 match suggestion {
332 Some(similar) => {
333 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
334 }
335 None => anyhow!("Column '{}' not found", object),
336 }
337 })?;
338
339 let value = self.table.get_value(row_index, col_index);
340 let trimmed_value = match value {
341 Some(DataValue::String(s)) => Some(DataValue::String(
342 Self::apply_trim(&s, trim_type).to_string(),
343 )),
344 Some(DataValue::InternedString(s)) => Some(DataValue::String(
345 Self::apply_trim(&s, trim_type).to_string(),
346 )),
347 Some(DataValue::Integer(n)) => {
348 let str_val = n.to_string();
349 Some(DataValue::String(
350 Self::apply_trim(&str_val, trim_type).to_string(),
351 ))
352 }
353 Some(DataValue::Float(f)) => {
354 let str_val = f.to_string();
355 Some(DataValue::String(
356 Self::apply_trim(&str_val, trim_type).to_string(),
357 ))
358 }
359 _ => Some(DataValue::String(String::new())),
360 };
361
362 let method_name = match trim_type {
363 "trim" => "Trim",
364 "trimstart" => "TrimStart",
365 "trimend" => "TrimEnd",
366 _ => "Trim",
367 };
368 Ok((trimmed_value, format!("{}.{}()", object, method_name)))
369 }
370
371 pub fn evaluate(&self, where_clause: &WhereClause, row_index: usize) -> Result<bool> {
373 if row_index < 3 {
375 debug!(
376 "RecursiveWhereEvaluator: evaluate() ENTRY - row {}, {} conditions, case_insensitive={}",
377 row_index,
378 where_clause.conditions.len(),
379 self.case_insensitive
380 );
381 }
382
383 if where_clause.conditions.is_empty() {
384 if row_index < 3 {
385 debug!("RecursiveWhereEvaluator: evaluate() EXIT - no conditions, returning true");
386 }
387 return Ok(true);
388 }
389
390 if row_index < 3 {
392 debug!(
393 "RecursiveWhereEvaluator: evaluate() - evaluating first condition for row {}",
394 row_index
395 );
396 }
397 let mut result = self.evaluate_condition(&where_clause.conditions[0], row_index)?;
398
399 for i in 1..where_clause.conditions.len() {
401 let next_result = self.evaluate_condition(&where_clause.conditions[i], row_index)?;
402
403 if let Some(connector) = &where_clause.conditions[i - 1].connector {
405 result = match connector {
406 LogicalOp::And => result && next_result,
407 LogicalOp::Or => result || next_result,
408 };
409 }
410 }
411
412 Ok(result)
413 }
414
415 fn evaluate_condition(&self, condition: &Condition, row_index: usize) -> Result<bool> {
416 if row_index < 3 {
418 debug!(
419 "RecursiveWhereEvaluator: evaluate_condition() ENTRY - row {}",
420 row_index
421 );
422 }
423 let result = self.evaluate_expression(&condition.expr, row_index);
424 if row_index < 3 {
425 debug!(
426 "RecursiveWhereEvaluator: evaluate_condition() EXIT - row {}, result = {:?}",
427 row_index, result
428 );
429 }
430 result
431 }
432
433 fn evaluate_expression(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
434 if row_index < 3 {
436 debug!(
437 "RecursiveWhereEvaluator: evaluate_expression() ENTRY - row {}, expr = {:?}",
438 row_index, expr
439 );
440 }
441
442 let result = match expr {
443 SqlExpression::BinaryOp { left, op, right } => {
444 self.evaluate_binary_op(left, op, right, row_index)
445 }
446 SqlExpression::InList { expr, values } => {
447 self.evaluate_in_list(expr, values, row_index, false)
448 }
449 SqlExpression::NotInList { expr, values } => {
450 let in_result = self.evaluate_in_list(expr, values, row_index, false)?;
451 Ok(!in_result)
452 }
453 SqlExpression::Between { expr, lower, upper } => {
454 self.evaluate_between(expr, lower, upper, row_index)
455 }
456 SqlExpression::Not { expr } => {
457 let inner_result = self.evaluate_expression(expr, row_index)?;
458 Ok(!inner_result)
459 }
460 SqlExpression::MethodCall {
461 object,
462 method,
463 args,
464 } => {
465 if row_index < 3 {
466 debug!("RecursiveWhereEvaluator: evaluate_expression() - found MethodCall, delegating to evaluate_method_call");
467 }
468 self.evaluate_method_call(object, method, args, row_index)
469 }
470 SqlExpression::CaseExpression {
471 when_branches,
472 else_branch,
473 } => {
474 if row_index < 3 {
475 debug!("RecursiveWhereEvaluator: evaluate_expression() - found CaseExpression, evaluating");
476 }
477 self.evaluate_case_expression_as_bool(when_branches, else_branch, row_index)
478 }
479 _ => {
480 if row_index < 3 {
481 debug!("RecursiveWhereEvaluator: evaluate_expression() - unsupported expression type, returning false");
482 }
483 Ok(false) }
485 };
486
487 if row_index < 3 {
488 debug!(
489 "RecursiveWhereEvaluator: evaluate_expression() EXIT - row {}, result = {:?}",
490 row_index, result
491 );
492 }
493 result
494 }
495
496 fn evaluate_binary_op(
497 &self,
498 left: &SqlExpression,
499 op: &str,
500 right: &SqlExpression,
501 row_index: usize,
502 ) -> Result<bool> {
503 if row_index < 3 {
505 debug!(
506 "RecursiveWhereEvaluator: evaluate_binary_op() ENTRY - row {}, op = '{}'",
507 row_index, op
508 );
509 }
510
511 let (cell_value, column_name) = match left {
513 SqlExpression::MethodCall {
514 object,
515 method,
516 args,
517 } => {
518 match method.to_lowercase().as_str() {
520 "length" => {
521 if !args.is_empty() {
522 return Err(anyhow::anyhow!("Length() takes no arguments"));
523 }
524 self.evaluate_length(object, row_index)?
525 }
526 "indexof" => {
527 if args.len() != 1 {
528 return Err(anyhow::anyhow!("IndexOf() requires exactly 1 argument"));
529 }
530 let search_str = self.extract_string_value(&args[0])?;
531 self.evaluate_indexof(object, &search_str, row_index)?
532 }
533 "trim" => {
534 if !args.is_empty() {
535 return Err(anyhow::anyhow!("Trim() takes no arguments"));
536 }
537 self.evaluate_trim(object, row_index, "trim")?
538 }
539 "trimstart" => {
540 if !args.is_empty() {
541 return Err(anyhow::anyhow!("TrimStart() takes no arguments"));
542 }
543 self.evaluate_trim(object, row_index, "trimstart")?
544 }
545 "trimend" => {
546 if !args.is_empty() {
547 return Err(anyhow::anyhow!("TrimEnd() takes no arguments"));
548 }
549 self.evaluate_trim(object, row_index, "trimend")?
550 }
551 _ => {
552 return Err(anyhow::anyhow!(
553 "Method '{}' cannot be used in comparisons",
554 method
555 ));
556 }
557 }
558 }
559 SqlExpression::BinaryOp {
560 left: _expr_left,
561 op: arith_op,
562 right: _expr_right,
563 } if matches!(arith_op.as_str(), "+" | "-" | "*" | "/") => {
564 let evaluator =
566 ArithmeticEvaluator::with_date_notation(self.table, self.date_notation.clone());
567 let computed_value = evaluator.evaluate(left, row_index)?;
568 if row_index < 3 {
569 debug!(
570 "RecursiveWhereEvaluator: evaluate_binary_op() - computed arithmetic expression = {:?}",
571 computed_value
572 );
573 }
574 (Some(computed_value), "computed_expression".to_string())
575 }
576 SqlExpression::FunctionCall { name, .. } => {
577 let evaluator =
579 ArithmeticEvaluator::with_date_notation(self.table, self.date_notation.clone());
580 let computed_value = evaluator.evaluate(left, row_index)?;
581 if row_index < 3 {
582 debug!(
583 "RecursiveWhereEvaluator: evaluate_binary_op() - computed function {} = {:?}",
584 name, computed_value
585 );
586 }
587 (Some(computed_value), format!("{}()", name))
588 }
589 _ => {
590 let column_name = self.extract_column_name(left)?;
592 if row_index < 3 {
593 debug!(
594 "RecursiveWhereEvaluator: evaluate_binary_op() - column_name = '{}'",
595 column_name
596 );
597 }
598
599 let col_index = self.table.get_column_index(&column_name).ok_or_else(|| {
600 let suggestion = self.find_similar_column(&column_name);
601 match suggestion {
602 Some(similar) => anyhow!(
603 "Column '{}' not found. Did you mean '{}'?",
604 column_name,
605 similar
606 ),
607 None => anyhow!("Column '{}' not found", column_name),
608 }
609 })?;
610
611 let cell_value = self.table.get_value(row_index, col_index).cloned();
612 (cell_value, column_name)
613 }
614 };
615
616 if row_index < 3 {
617 debug!(
618 "RecursiveWhereEvaluator: evaluate_binary_op() - row {} column '{}' value = {:?}",
619 row_index, column_name, cell_value
620 );
621 }
622
623 let compare_value = self.extract_value(right)?;
625
626 match (cell_value, op.to_uppercase().as_str(), &compare_value) {
628 (Some(DataValue::String(ref a)), "=", ExprValue::String(b)) => {
629 if let (Ok(date_a), Ok(date_b)) = (
631 self.parse_datetime_with_notation(a),
632 self.parse_datetime_with_notation(b),
633 ) {
634 if row_index < 3 {
635 debug!(
636 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' = '{}' = {}",
637 date_a.format("%Y-%m-%d %H:%M:%S"),
638 date_b.format("%Y-%m-%d %H:%M:%S"),
639 date_a == date_b
640 );
641 }
642 Ok(date_a == date_b)
643 } else {
644 if row_index < 3 {
645 debug!(
646 "RecursiveWhereEvaluator: String comparison '{}' = '{}' (case_insensitive={})",
647 a, b, self.case_insensitive
648 );
649 }
650 if self.case_insensitive {
651 Ok(a.to_lowercase() == b.to_lowercase())
652 } else {
653 Ok(a == b)
654 }
655 }
656 }
657 (Some(DataValue::InternedString(ref a)), "=", ExprValue::String(b)) => {
658 if let (Ok(date_a), Ok(date_b)) = (
660 self.parse_datetime_with_notation(a.as_ref()),
661 self.parse_datetime_with_notation(b),
662 ) {
663 if row_index < 3 {
664 debug!(
665 "RecursiveWhereEvaluator: Date comparison (from interned strings) '{}' = '{}' = {}",
666 date_a.format("%Y-%m-%d %H:%M:%S"),
667 date_b.format("%Y-%m-%d %H:%M:%S"),
668 date_a == date_b
669 );
670 }
671 Ok(date_a == date_b)
672 } else {
673 if row_index < 3 {
674 debug!(
675 "RecursiveWhereEvaluator: InternedString comparison '{}' = '{}' (case_insensitive={})",
676 a, b, self.case_insensitive
677 );
678 }
679 if self.case_insensitive {
680 Ok(a.to_lowercase() == b.to_lowercase())
681 } else {
682 Ok(a.as_ref() == b)
683 }
684 }
685 }
686 (Some(DataValue::String(ref a)), "!=", ExprValue::String(b))
687 | (Some(DataValue::String(ref a)), "<>", ExprValue::String(b)) => {
688 if let (Ok(date_a), Ok(date_b)) = (
690 self.parse_datetime_with_notation(a),
691 self.parse_datetime_with_notation(b),
692 ) {
693 if row_index < 3 {
694 debug!(
695 "RecursiveWhereEvaluator: Date comparison (from strings) '{}' != '{}' = {}",
696 date_a.format("%Y-%m-%d %H:%M:%S"),
697 date_b.format("%Y-%m-%d %H:%M:%S"),
698 date_a != date_b
699 );
700 }
701 Ok(date_a != date_b)
702 } else {
703 if row_index < 3 {
704 debug!(
705 "RecursiveWhereEvaluator: String comparison '{}' != '{}' (case_insensitive={})",
706 a, b, self.case_insensitive
707 );
708 }
709 if self.case_insensitive {
710 Ok(a.to_lowercase() != b.to_lowercase())
711 } else {
712 Ok(a != b)
713 }
714 }
715 }
716 (Some(DataValue::InternedString(ref a)), "!=", ExprValue::String(b))
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))
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 (Some(DataValue::Integer(a)), "<=", ExprValue::Number(b)) => Ok(a as f64 <= *b),
922
923 (Some(DataValue::Float(a)), "=", ExprValue::Number(b)) => {
924 Ok((a - b).abs() < f64::EPSILON)
925 }
926 (Some(DataValue::Float(a)), "!=", ExprValue::Number(b))
927 | (Some(DataValue::Float(a)), "<>", ExprValue::Number(b)) => {
928 Ok((a - b).abs() >= f64::EPSILON)
929 }
930 (Some(DataValue::Float(a)), ">", ExprValue::Number(b)) => Ok(a > *b),
931 (Some(DataValue::Float(a)), ">=", ExprValue::Number(b)) => Ok(a >= *b),
932 (Some(DataValue::Float(a)), "<", ExprValue::Number(b)) => Ok(a < *b),
933 (Some(DataValue::Float(a)), "<=", ExprValue::Number(b)) => Ok(a <= *b),
934
935 (Some(DataValue::Boolean(a)), "=", ExprValue::Boolean(b)) => Ok(a == *b),
937 (Some(DataValue::Boolean(a)), "!=", ExprValue::Boolean(b))
938 | (Some(DataValue::Boolean(a)), "<>", ExprValue::Boolean(b)) => Ok(a != *b),
939
940 (Some(DataValue::Boolean(a)), "=", ExprValue::String(b)) => {
942 let bool_str = a.to_string();
943 if self.case_insensitive {
944 Ok(bool_str.to_lowercase() == b.to_lowercase())
945 } else {
946 Ok(bool_str == *b)
947 }
948 }
949 (Some(DataValue::Boolean(a)), "!=", ExprValue::String(b))
950 | (Some(DataValue::Boolean(a)), "<>", ExprValue::String(b)) => {
951 let bool_str = a.to_string();
952 if self.case_insensitive {
953 Ok(bool_str.to_lowercase() != b.to_lowercase())
954 } else {
955 Ok(bool_str != *b)
956 }
957 }
958
959 (Some(DataValue::String(ref text)), "LIKE", ExprValue::String(pattern)) => {
961 let regex_pattern = pattern.replace('%', ".*").replace('_', ".");
962 let regex = regex::RegexBuilder::new(&format!("^{}$", regex_pattern))
963 .case_insensitive(true)
964 .build()
965 .map_err(|e| anyhow::anyhow!("Invalid LIKE pattern: {}", e))?;
966 Ok(regex.is_match(text))
967 }
968 (Some(DataValue::InternedString(ref text)), "LIKE", ExprValue::String(pattern)) => {
969 let regex_pattern = pattern.replace('%', ".*").replace('_', ".");
970 let regex = regex::RegexBuilder::new(&format!("^{}$", regex_pattern))
971 .case_insensitive(true)
972 .build()
973 .map_err(|e| anyhow::anyhow!("Invalid LIKE pattern: {}", e))?;
974 Ok(regex.is_match(text.as_ref()))
975 }
976
977 (None, "IS", ExprValue::Null) | (Some(DataValue::Null), "IS", ExprValue::Null) => {
979 Ok(true)
980 }
981 (Some(_), "IS", ExprValue::Null) => Ok(false),
982 (None, "IS NOT", ExprValue::Null)
983 | (Some(DataValue::Null), "IS NOT", ExprValue::Null) => Ok(false),
984 (Some(_), "IS NOT", ExprValue::Null) => Ok(true),
985
986 (Some(DataValue::String(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
988 if row_index < 3 {
989 debug!(
990 "RecursiveWhereEvaluator: DateTime comparison '{}' {} '{}' - attempting parse",
991 date_str,
992 op_str,
993 dt.format("%Y-%m-%d %H:%M:%S")
994 );
995 }
996
997 match self.parse_datetime_with_notation(date_str) {
999 Ok(parsed_dt) => {
1000 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
1001 if row_index < 3 {
1002 debug!(
1003 "RecursiveWhereEvaluator: DateTime parsed successfully: '{}' {} '{}' = {}",
1004 parsed_dt.format("%Y-%m-%d %H:%M:%S"),
1005 op_str,
1006 dt.format("%Y-%m-%d %H:%M:%S"),
1007 result
1008 );
1009 }
1010 Ok(result)
1011 }
1012 Err(_) => {
1013 if row_index < 3 {
1014 debug!(
1015 "RecursiveWhereEvaluator: DateTime parse FAILED for '{}' - no matching format",
1016 date_str
1017 );
1018 }
1019 Ok(false)
1020 }
1021 }
1022 }
1023 (Some(DataValue::InternedString(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
1024 if row_index < 3 {
1025 debug!(
1026 "RecursiveWhereEvaluator: DateTime comparison (interned) '{}' {} '{}' - attempting parse",
1027 date_str,
1028 op_str,
1029 dt.format("%Y-%m-%d %H:%M:%S")
1030 );
1031 }
1032
1033 match self.parse_datetime_with_notation(date_str.as_ref()) {
1035 Ok(parsed_dt) => {
1036 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
1037 if row_index < 3 {
1038 debug!(
1039 "RecursiveWhereEvaluator: DateTime parsed successfully: '{}' {} '{}' = {}",
1040 parsed_dt.format("%Y-%m-%d %H:%M:%S"),
1041 op_str,
1042 dt.format("%Y-%m-%d %H:%M:%S"),
1043 result
1044 );
1045 }
1046 Ok(result)
1047 }
1048 Err(_) => {
1049 if row_index < 3 {
1050 debug!(
1051 "RecursiveWhereEvaluator: DateTime parse FAILED for '{}' - no matching format",
1052 date_str
1053 );
1054 }
1055 Ok(false)
1056 }
1057 }
1058 }
1059
1060 (Some(DataValue::DateTime(ref date_str)), op_str, ExprValue::DateTime(dt)) => {
1062 if row_index < 3 {
1063 debug!(
1064 "RecursiveWhereEvaluator: DateTime vs DateTime comparison '{}' {} '{}' - direct comparison",
1065 date_str, op_str, dt.format("%Y-%m-%d %H:%M:%S")
1066 );
1067 }
1068
1069 match self.parse_datetime_with_notation(date_str) {
1071 Ok(parsed_dt) => {
1072 let result = Self::compare_datetime(op_str, &parsed_dt, dt);
1073 if row_index < 3 {
1074 debug!(
1075 "RecursiveWhereEvaluator: DateTime vs DateTime parsed successfully: '{}' {} '{}' = {}",
1076 parsed_dt.format("%Y-%m-%d %H:%M:%S"), op_str, dt.format("%Y-%m-%d %H:%M:%S"), result
1077 );
1078 }
1079 Ok(result)
1080 }
1081 Err(_) => {
1082 if row_index < 3 {
1083 debug!(
1084 "RecursiveWhereEvaluator: DateTime vs DateTime parse FAILED for '{}' - no matching format",
1085 date_str
1086 );
1087 }
1088 Ok(false)
1089 }
1090 }
1091 }
1092
1093 _ => Ok(false),
1094 }
1095 }
1096
1097 fn evaluate_in_list(
1098 &self,
1099 expr: &SqlExpression,
1100 values: &[SqlExpression],
1101 row_index: usize,
1102 _ignore_case: bool,
1103 ) -> Result<bool> {
1104 let column_name = self.extract_column_name(expr)?;
1105 let col_index = self
1106 .table
1107 .get_column_index(&column_name)
1108 .ok_or_else(|| anyhow::anyhow!("Column '{}' not found", column_name))?;
1109
1110 let cell_value = self.table.get_value(row_index, col_index).cloned();
1111
1112 for value_expr in values {
1113 let compare_value = self.extract_value(value_expr)?;
1114 let matches = match (cell_value.as_ref(), &compare_value) {
1115 (Some(DataValue::String(a)), ExprValue::String(b)) => {
1116 if self.case_insensitive {
1117 if row_index < 3 {
1118 debug!("RecursiveWhereEvaluator: IN list string comparison '{}' in '{}' (case_insensitive={})", a, b, self.case_insensitive);
1119 }
1120 a.to_lowercase() == b.to_lowercase()
1121 } else {
1122 a == b
1123 }
1124 }
1125 (Some(DataValue::InternedString(a)), ExprValue::String(b)) => {
1126 if self.case_insensitive {
1127 if row_index < 3 {
1128 debug!("RecursiveWhereEvaluator: IN list interned string comparison '{}' in '{}' (case_insensitive={})", a, b, self.case_insensitive);
1129 }
1130 a.to_lowercase() == b.to_lowercase()
1131 } else {
1132 a.as_ref() == b
1133 }
1134 }
1135 (Some(DataValue::Integer(a)), ExprValue::Number(b)) => *a as f64 == *b,
1136 (Some(DataValue::Float(a)), ExprValue::Number(b)) => (*a - b).abs() < f64::EPSILON,
1137 _ => false,
1138 };
1139
1140 if matches {
1141 return Ok(true);
1142 }
1143 }
1144
1145 Ok(false)
1146 }
1147
1148 fn evaluate_between(
1149 &self,
1150 expr: &SqlExpression,
1151 lower: &SqlExpression,
1152 upper: &SqlExpression,
1153 row_index: usize,
1154 ) -> Result<bool> {
1155 let column_name = self.extract_column_name(expr)?;
1156 let col_index = self
1157 .table
1158 .get_column_index(&column_name)
1159 .ok_or_else(|| anyhow::anyhow!("Column '{}' not found", column_name))?;
1160
1161 let cell_value = self.table.get_value(row_index, col_index).cloned();
1162 let lower_value = self.extract_value(lower)?;
1163 let upper_value = self.extract_value(upper)?;
1164
1165 match (cell_value, &lower_value, &upper_value) {
1166 (Some(DataValue::Integer(n)), ExprValue::Number(l), ExprValue::Number(u)) => {
1167 Ok(n as f64 >= *l && n as f64 <= *u)
1168 }
1169 (Some(DataValue::Float(n)), ExprValue::Number(l), ExprValue::Number(u)) => {
1170 Ok(n >= *l && n <= *u)
1171 }
1172 (Some(DataValue::String(ref s)), ExprValue::String(l), ExprValue::String(u)) => {
1173 Ok(s >= l && s <= u)
1174 }
1175 (
1176 Some(DataValue::InternedString(ref s)),
1177 ExprValue::String(l),
1178 ExprValue::String(u),
1179 ) => Ok(s.as_ref() >= l && s.as_ref() <= u),
1180 _ => Ok(false),
1181 }
1182 }
1183
1184 fn evaluate_method_call(
1185 &self,
1186 object: &str,
1187 method: &str,
1188 args: &[SqlExpression],
1189 row_index: usize,
1190 ) -> Result<bool> {
1191 if row_index < 3 {
1192 debug!(
1193 "RecursiveWhereEvaluator: evaluate_method_call - object='{}', method='{}', row={}",
1194 object, method, row_index
1195 );
1196 }
1197
1198 let col_index = self.table.get_column_index(object).ok_or_else(|| {
1200 let suggestion = self.find_similar_column(object);
1201 match suggestion {
1202 Some(similar) => {
1203 anyhow!("Column '{}' not found. Did you mean '{}'?", object, similar)
1204 }
1205 None => anyhow!("Column '{}' not found", object),
1206 }
1207 })?;
1208
1209 let cell_value = self.table.get_value(row_index, col_index).cloned();
1210 if row_index < 3 {
1211 debug!(
1212 "RecursiveWhereEvaluator: Row {} column '{}' value = {:?}",
1213 row_index, object, cell_value
1214 );
1215 }
1216
1217 match method.to_lowercase().as_str() {
1218 "contains" => {
1219 if args.len() != 1 {
1220 return Err(anyhow::anyhow!("Contains requires exactly 1 argument"));
1221 }
1222 let search_str = self.extract_string_value(&args[0])?;
1223 let search_lower = search_str.to_lowercase();
1225
1226 match cell_value {
1228 Some(DataValue::String(ref s)) => {
1229 let result = s.to_lowercase().contains(&search_lower);
1230 if row_index < 3 {
1232 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on '{}' = {} (case-insensitive)", row_index, search_str, s, result);
1233 }
1234 Ok(result)
1235 }
1236 Some(DataValue::InternedString(ref s)) => {
1237 let result = s.to_lowercase().contains(&search_lower);
1238 if row_index < 3 {
1240 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on interned '{}' = {} (case-insensitive)", row_index, search_str, s, result);
1241 }
1242 Ok(result)
1243 }
1244 Some(DataValue::Integer(n)) => {
1245 let str_val = n.to_string();
1246 let result = str_val.contains(&search_str);
1247 if row_index < 3 {
1248 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on integer '{}' = {}", row_index, search_str, str_val, result);
1249 }
1250 Ok(result)
1251 }
1252 Some(DataValue::Float(f)) => {
1253 let str_val = f.to_string();
1254 let result = str_val.contains(&search_str);
1255 if row_index < 3 {
1256 debug!(
1257 "RecursiveWhereEvaluator: Row {} contains('{}') on float '{}' = {}",
1258 row_index, search_str, str_val, result
1259 );
1260 }
1261 Ok(result)
1262 }
1263 Some(DataValue::Boolean(b)) => {
1264 let str_val = b.to_string();
1265 let result = str_val.contains(&search_str);
1266 if row_index < 3 {
1267 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on boolean '{}' = {}", row_index, search_str, str_val, result);
1268 }
1269 Ok(result)
1270 }
1271 Some(DataValue::DateTime(dt)) => {
1272 let result = dt.contains(&search_str);
1274 if row_index < 3 {
1275 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on datetime '{}' = {}", row_index, search_str, dt, result);
1276 }
1277 Ok(result)
1278 }
1279 _ => {
1280 if row_index < 3 {
1281 debug!("RecursiveWhereEvaluator: Row {} contains('{}') on null/empty value = false", row_index, search_str);
1282 }
1283 Ok(false)
1284 }
1285 }
1286 }
1287 "startswith" => {
1288 if args.len() != 1 {
1289 return Err(anyhow::anyhow!("StartsWith requires exactly 1 argument"));
1290 }
1291 let prefix = self.extract_string_value(&args[0])?;
1292
1293 match cell_value {
1295 Some(DataValue::String(ref s)) => {
1296 Ok(s.to_lowercase().starts_with(&prefix.to_lowercase()))
1297 }
1298 Some(DataValue::InternedString(ref s)) => {
1299 Ok(s.to_lowercase().starts_with(&prefix.to_lowercase()))
1300 }
1301 Some(DataValue::Integer(n)) => Ok(n.to_string().starts_with(&prefix)),
1302 Some(DataValue::Float(f)) => Ok(f.to_string().starts_with(&prefix)),
1303 Some(DataValue::Boolean(b)) => Ok(b.to_string().starts_with(&prefix)),
1304 Some(DataValue::DateTime(dt)) => Ok(dt.starts_with(&prefix)),
1305 _ => Ok(false),
1306 }
1307 }
1308 "endswith" => {
1309 if args.len() != 1 {
1310 return Err(anyhow::anyhow!("EndsWith requires exactly 1 argument"));
1311 }
1312 let suffix = self.extract_string_value(&args[0])?;
1313
1314 match cell_value {
1316 Some(DataValue::String(ref s)) => {
1317 Ok(s.to_lowercase().ends_with(&suffix.to_lowercase()))
1318 }
1319 Some(DataValue::InternedString(ref s)) => {
1320 Ok(s.to_lowercase().ends_with(&suffix.to_lowercase()))
1321 }
1322 Some(DataValue::Integer(n)) => Ok(n.to_string().ends_with(&suffix)),
1323 Some(DataValue::Float(f)) => Ok(f.to_string().ends_with(&suffix)),
1324 Some(DataValue::Boolean(b)) => Ok(b.to_string().ends_with(&suffix)),
1325 Some(DataValue::DateTime(dt)) => Ok(dt.ends_with(&suffix)),
1326 _ => Ok(false),
1327 }
1328 }
1329 _ => Err(anyhow::anyhow!("Unsupported method: {}", method)),
1330 }
1331 }
1332
1333 fn extract_column_name(&self, expr: &SqlExpression) -> Result<String> {
1334 match expr {
1335 SqlExpression::Column(name) => Ok(name.clone()),
1336 _ => Err(anyhow::anyhow!("Expected column name, got: {:?}", expr)),
1337 }
1338 }
1339
1340 fn extract_string_value(&self, expr: &SqlExpression) -> Result<String> {
1341 match expr {
1342 SqlExpression::StringLiteral(s) => Ok(s.clone()),
1343 _ => Err(anyhow::anyhow!("Expected string literal, got: {:?}", expr)),
1344 }
1345 }
1346
1347 fn extract_value(&self, expr: &SqlExpression) -> Result<ExprValue> {
1348 match expr {
1349 SqlExpression::StringLiteral(s) => Ok(ExprValue::String(s.clone())),
1350 SqlExpression::BooleanLiteral(b) => Ok(ExprValue::Boolean(*b)),
1351 SqlExpression::NumberLiteral(n) => {
1352 if let Ok(num) = n.parse::<f64>() {
1353 Ok(ExprValue::Number(num))
1354 } else {
1355 Ok(ExprValue::String(n.clone()))
1356 }
1357 }
1358 SqlExpression::DateTimeConstructor {
1359 year,
1360 month,
1361 day,
1362 hour,
1363 minute,
1364 second,
1365 } => {
1366 let naive_date = NaiveDate::from_ymd_opt(*year, *month, *day)
1368 .ok_or_else(|| anyhow::anyhow!("Invalid date: {}-{}-{}", year, month, day))?;
1369 let naive_time = NaiveTime::from_hms_opt(
1370 hour.unwrap_or(0),
1371 minute.unwrap_or(0),
1372 second.unwrap_or(0),
1373 )
1374 .ok_or_else(|| anyhow::anyhow!("Invalid time"))?;
1375 let naive_datetime = NaiveDateTime::new(naive_date, naive_time);
1376 let datetime = Utc.from_utc_datetime(&naive_datetime);
1377 Ok(ExprValue::DateTime(datetime))
1378 }
1379 SqlExpression::DateTimeToday {
1380 hour,
1381 minute,
1382 second,
1383 } => {
1384 let today = Local::now().date_naive();
1386 let time = NaiveTime::from_hms_opt(
1387 hour.unwrap_or(0),
1388 minute.unwrap_or(0),
1389 second.unwrap_or(0),
1390 )
1391 .ok_or_else(|| anyhow::anyhow!("Invalid time"))?;
1392 let naive_datetime = NaiveDateTime::new(today, time);
1393 let datetime = Utc.from_utc_datetime(&naive_datetime);
1394 Ok(ExprValue::DateTime(datetime))
1395 }
1396 _ => Ok(ExprValue::Null),
1397 }
1398 }
1399
1400 fn evaluate_case_expression_as_bool(
1402 &self,
1403 when_branches: &[crate::sql::recursive_parser::WhenBranch],
1404 else_branch: &Option<Box<SqlExpression>>,
1405 row_index: usize,
1406 ) -> Result<bool> {
1407 debug!(
1408 "RecursiveWhereEvaluator: evaluating CASE expression as bool for row {}",
1409 row_index
1410 );
1411
1412 for branch in when_branches {
1414 let condition_result = self.evaluate_expression(&branch.condition, row_index)?;
1416
1417 if condition_result {
1418 debug!("CASE: WHEN condition matched, evaluating result expression as bool");
1419 return self.evaluate_expression_as_bool(&branch.result, row_index);
1421 }
1422 }
1423
1424 match else_branch {
1426 Some(else_expr) => {
1427 debug!("CASE: No WHEN matched, evaluating ELSE expression as bool");
1428 self.evaluate_expression_as_bool(else_expr, row_index)
1429 }
1430 None => {
1431 debug!("CASE: No WHEN matched and no ELSE, returning false");
1432 Ok(false)
1433 }
1434 }
1435 }
1436
1437 fn evaluate_expression_as_bool(&self, expr: &SqlExpression, row_index: usize) -> Result<bool> {
1439 match expr {
1440 SqlExpression::BinaryOp { .. }
1442 | SqlExpression::InList { .. }
1443 | SqlExpression::NotInList { .. }
1444 | SqlExpression::Between { .. }
1445 | SqlExpression::Not { .. }
1446 | SqlExpression::MethodCall { .. } => self.evaluate_expression(expr, row_index),
1447 SqlExpression::CaseExpression {
1449 when_branches,
1450 else_branch,
1451 } => self.evaluate_case_expression_as_bool(when_branches, else_branch, row_index),
1452 _ => {
1454 let evaluator =
1456 crate::data::arithmetic_evaluator::ArithmeticEvaluator::with_date_notation(
1457 self.table,
1458 self.date_notation.clone(),
1459 );
1460 let value = evaluator.evaluate(expr, row_index)?;
1461
1462 match value {
1463 crate::data::datatable::DataValue::Boolean(b) => Ok(b),
1464 crate::data::datatable::DataValue::Integer(i) => Ok(i != 0),
1465 crate::data::datatable::DataValue::Float(f) => Ok(f != 0.0),
1466 crate::data::datatable::DataValue::Null => Ok(false),
1467 crate::data::datatable::DataValue::String(s) => Ok(!s.is_empty()),
1468 crate::data::datatable::DataValue::InternedString(s) => Ok(!s.is_empty()),
1469 _ => Ok(true), }
1471 }
1472 }
1473 }
1474}
1475
1476enum ExprValue {
1477 String(String),
1478 Number(f64),
1479 Boolean(bool),
1480 DateTime(DateTime<Utc>),
1481 Null,
1482}