1use crate::parser::Parser;
2use crate::error::ParseError;
3use crate::arena::*;
4use crate::tokens::TokenType;
5
6use std::collections::HashMap;
7use std::fmt;
8
9#[derive(Debug, Clone, PartialEq)]
15pub enum RuntimeValue {
16 Integer(i64),
18 Float(f64),
20 String(String),
22 Boolean(bool),
24 Null,
26}
27
28#[derive(Debug, Clone, PartialEq)]
30pub enum EvalError {
31 EvalParseError(String),
34
35 UnboundVariable {
37 name: String,
39 },
40
41 TypeError {
43 operation: String,
45 expected: String,
47 actual: String,
49 context: String,
51 },
52
53 NullInOperation {
55 operation: String,
57 context: String,
59 },
60
61 DivisionByZero {
63 expression: String,
65 },
66
67 InvalidLiteral {
69 literal: String,
71 literal_type: String,
73 error: String,
75 },
76}
77
78impl fmt::Display for EvalError {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 match self {
81 EvalError::EvalParseError(msg) => write!(f, "Parse error: {}", msg),
82 EvalError::UnboundVariable { name } => {
83 write!(f, "Unbound variable '{}' - not found in value map", name)
84 }
85 EvalError::TypeError { operation, expected, actual, context } => {
86 write!(f, "Type error in {}: expected {}, got {} (context: {})",
87 operation, expected, actual, context)
88 }
89 EvalError::NullInOperation { operation, context } => {
90 write!(f, "NULL value in {} operation (context: {}). NULL is only allowed in IS NULL/IS NOT NULL",
91 operation, context)
92 }
93 EvalError::DivisionByZero { expression } => {
94 write!(f, "Division by zero in expression: {}", expression)
95 }
96 EvalError::InvalidLiteral { literal, literal_type, error } => {
97 write!(f, "Invalid {} literal '{}': {}", literal_type, literal, error)
98 }
99 }
100 }
101}
102
103impl std::error::Error for EvalError {}
104
105impl From<String> for EvalError {
106 fn from(msg: String) -> Self {
107 EvalError::EvalParseError(msg)
108 }
109}
110
111impl From<&str> for EvalError {
112 fn from(msg: &str) -> Self {
113 EvalError::EvalParseError(msg.to_string())
114 }
115}
116
117impl From<ParseError> for EvalError {
118 fn from(msg: ParseError) -> Self {
119 EvalError::EvalParseError(msg.to_string())
120 }
121}
122
123pub fn evaluate(input: &str, map: &HashMap<String, RuntimeValue>) -> Result<bool, EvalError> {
145 let evaluator = Evaluator::new(input, map)?;
146 let result = evaluator.eval_node(evaluator.root)?;
147 match result {
148 EvalValue::Bool(b) => Ok(b),
149 other => Err(EvalError::TypeError {
150 operation: "top-level evaluation".to_string(),
151 expected: "boolean".to_string(),
152 actual: other.type_name().to_string(),
153 context: input.to_string(),
154 }),
155 }
156}
157
158#[derive(Debug, Clone, PartialEq)]
163enum EvalValue {
164 Integer(i64),
165 Float(f64),
166 Str(String),
167 Bool(bool),
168 Null,
169}
170
171impl EvalValue {
172 fn type_name(&self) -> &'static str {
173 match self {
174 EvalValue::Integer(_) => "integer",
175 EvalValue::Float(_) => "float",
176 EvalValue::Str(_) => "string",
177 EvalValue::Bool(_) => "boolean",
178 EvalValue::Null => "null",
179 }
180 }
181}
182
183impl From<&RuntimeValue> for EvalValue {
184 fn from(rv: &RuntimeValue) -> Self {
185 match rv {
186 RuntimeValue::Integer(i) => EvalValue::Integer(*i),
187 RuntimeValue::Float(f) => EvalValue::Float(*f),
188 RuntimeValue::String(s) => EvalValue::Str(s.clone()),
189 RuntimeValue::Boolean(b) => EvalValue::Bool(*b),
190 RuntimeValue::Null => EvalValue::Null,
191 }
192 }
193}
194
195struct Evaluator<'a> {
200 parser: Parser,
201 root: NodeId,
202 value_map: &'a HashMap<String, RuntimeValue>,
203}
204
205impl<'a> Evaluator<'a> {
206 fn new(input: &str, value_map: &'a HashMap<String, RuntimeValue>) -> Result<Self, EvalError> {
207 let mut parser = Parser::new(input.to_string())?;
208 let root = parser.parse()?;
209 Ok(Evaluator {
210 parser,
211 root,
212 value_map,
213 })
214 }
215
216 fn arena(&self) -> &Arena {
217 self.parser.arena()
218 }
219
220 fn input(&self) -> &str {
221 self.parser.input()
222 }
223
224 fn eval_node(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
229 match self.arena().get_node(node_id) {
230 AstNode::JmsSelector(_) => self.eval_jms_selector(node_id),
231 AstNode::OrExpression(_) => self.eval_or(node_id),
232 AstNode::AndExpression(_) => self.eval_and(node_id),
233 AstNode::EqualityExpression(_) => self.eval_equality(node_id),
234 AstNode::ComparisonExpression(_) => self.eval_comparison(node_id),
235 AstNode::AddExpression(_) => self.eval_add(node_id),
236 AstNode::MultExpr(_) => self.eval_mult(node_id),
237 AstNode::UnaryExpr(_) => self.eval_unary(node_id),
238 AstNode::PrimaryExpr(_) => self.eval_primary(node_id),
239 AstNode::Literal(_) => self.eval_literal(node_id),
240 AstNode::StringLiteral(_) => self.eval_string_literal(node_id),
241 AstNode::Variable(_) => self.eval_variable(node_id),
242 }
243 }
244
245 fn eval_jms_selector(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
250 let children = self.get_children(node_id);
251 self.eval_node(children[0])
252 }
253
254 fn eval_or(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
255 let children = self.get_children(node_id);
256 if children.len() == 1 {
258 return self.eval_node(children[0]);
259 }
260 for child_id in &children {
261 let val = self.eval_node(*child_id)?;
262 match val {
263 EvalValue::Bool(true) => return Ok(EvalValue::Bool(true)),
264 EvalValue::Bool(false) => {}
265 other => {
266 return Err(EvalError::TypeError {
267 operation: "OR".to_string(),
268 expected: "boolean".to_string(),
269 actual: other.type_name().to_string(),
270 context: self.input().to_string(),
271 });
272 }
273 }
274 }
275 Ok(EvalValue::Bool(false))
276 }
277
278 fn eval_and(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
279 let children = self.get_children(node_id);
280 if children.len() == 1 {
282 return self.eval_node(children[0]);
283 }
284 for child_id in &children {
285 let val = self.eval_node(*child_id)?;
286 match val {
287 EvalValue::Bool(false) => return Ok(EvalValue::Bool(false)),
288 EvalValue::Bool(true) => {}
289 other => {
290 return Err(EvalError::TypeError {
291 operation: "AND".to_string(),
292 expected: "boolean".to_string(),
293 actual: other.type_name().to_string(),
294 context: self.input().to_string(),
295 });
296 }
297 }
298 }
299 Ok(EvalValue::Bool(true))
300 }
301
302 fn eval_equality(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
303 let (children, operators) = match self.arena().get_node(node_id) {
304 AstNode::EqualityExpression(n) => (n.children.clone(), n.operators.clone()),
305 other => return Err(EvalError::EvalParseError(
306 format!("Internal error: expected EqualityExpression node, found {:?}", other),
307 )),
308 };
309
310 let mut current = self.eval_node(children[0])?;
311 let mut child_idx = 1;
312
313 for op in &operators {
314 match op {
315 EqualityOp::Equal => {
316 let right = self.eval_node(children[child_idx])?;
317 child_idx += 1;
318 current = self.eval_eq_values(¤t, &right, "Equal")?;
319 }
320 EqualityOp::NotEqual => {
321 let right = self.eval_node(children[child_idx])?;
322 child_idx += 1;
323 let eq_result = self.eval_eq_values(¤t, &right, "NotEqual")?;
324 current = match eq_result {
325 EvalValue::Bool(b) => EvalValue::Bool(!b),
326 other => return Err(EvalError::EvalParseError(
327 format!("Internal error: equality comparison returned non-boolean {:?}", other.type_name()),
328 )),
329 };
330 }
331 EqualityOp::IsNull => {
332 current = EvalValue::Bool(matches!(current, EvalValue::Null));
333 }
334 EqualityOp::IsNotNull => {
335 current = EvalValue::Bool(!matches!(current, EvalValue::Null));
336 }
337 }
338 }
339
340 Ok(current)
341 }
342
343 fn eval_comparison(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
344 let (children, operators) = match self.arena().get_node(node_id) {
345 AstNode::ComparisonExpression(n) => (n.children.clone(), n.operators.clone()),
346 other => return Err(EvalError::EvalParseError(
347 format!("Internal error: expected ComparisonExpression node, found {:?}", other),
348 )),
349 };
350
351 let mut current = self.eval_node(children[0])?;
352 let mut child_idx = 1;
353
354 for op in &operators {
355 match op {
356 ComparisonOp::GreaterThan
357 | ComparisonOp::GreaterThanEqual
358 | ComparisonOp::LessThan
359 | ComparisonOp::LessThanEqual => {
360 let right = self.eval_node(children[child_idx])?;
361 child_idx += 1;
362 current = self.eval_ordering_comparison(¤t, &right, *op)?;
363 }
364 ComparisonOp::Like | ComparisonOp::NotLike => {
365 let pattern = self.eval_node(children[child_idx])?;
366 child_idx += 1;
367 current = self.eval_like(¤t, &pattern, None, *op)?;
368 }
369 ComparisonOp::LikeEscape | ComparisonOp::NotLikeEscape => {
370 let pattern = self.eval_node(children[child_idx])?;
371 child_idx += 1;
372 let escape = self.eval_node(children[child_idx])?;
373 child_idx += 1;
374 let escape_char = match &escape {
375 EvalValue::Str(s) => {
376 if s.len() != 1 {
377 return Err(EvalError::TypeError {
378 operation: "LIKE ESCAPE".to_string(),
379 expected: "single character string".to_string(),
380 actual: format!("string of length {}", s.len()),
381 context: self.input().to_string(),
382 });
383 }
384 Some(s.chars().next().unwrap())
385 }
386 _ => {
387 return Err(EvalError::TypeError {
388 operation: "LIKE ESCAPE".to_string(),
389 expected: "string".to_string(),
390 actual: escape.type_name().to_string(),
391 context: self.input().to_string(),
392 });
393 }
394 };
395 let base_op = if *op == ComparisonOp::LikeEscape {
396 ComparisonOp::Like
397 } else {
398 ComparisonOp::NotLike
399 };
400 current = self.eval_like(¤t, &pattern, escape_char, base_op)?;
401 }
402 ComparisonOp::Between | ComparisonOp::NotBetween => {
403 let low = self.eval_node(children[child_idx])?;
404 child_idx += 1;
405 let high = self.eval_node(children[child_idx])?;
406 child_idx += 1;
407 current = self.eval_between(¤t, &low, &high, *op)?;
408 }
409 ComparisonOp::In | ComparisonOp::NotIn => {
410 let elements: Vec<EvalValue> = children[child_idx..]
411 .iter()
412 .map(|id| self.eval_node(*id))
413 .collect::<Result<Vec<_>, _>>()?;
414 child_idx = children.len();
415 current = self.eval_in(¤t, &elements, *op)?;
416 }
417 }
418 }
419
420 Ok(current)
421 }
422
423 fn eval_add(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
424 let (children, operators) = match self.arena().get_node(node_id) {
425 AstNode::AddExpression(n) => (n.children.clone(), n.operators.clone()),
426 other => return Err(EvalError::EvalParseError(
427 format!("Internal error: expected AddExpression node, found {:?}", other),
428 )),
429 };
430
431 let mut result = self.eval_node(children[0])?;
432 for (i, op) in operators.iter().enumerate() {
433 let right = self.eval_node(children[i + 1])?;
434 result = self.eval_arithmetic_add(&result, &right, *op)?;
435 }
436 Ok(result)
437 }
438
439 fn eval_mult(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
440 let (children, operators) = match self.arena().get_node(node_id) {
441 AstNode::MultExpr(n) => (n.children.clone(), n.operators.clone()),
442 other => return Err(EvalError::EvalParseError(
443 format!("Internal error: expected MultExpr node, found {:?}", other),
444 )),
445 };
446
447 let mut result = self.eval_node(children[0])?;
448 for (i, op) in operators.iter().enumerate() {
449 let right = self.eval_node(children[i + 1])?;
450 result = self.eval_arithmetic_mult(&result, &right, *op)?;
451 }
452 Ok(result)
453 }
454
455 fn eval_unary(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
456 let (children, operator) = match self.arena().get_node(node_id) {
457 AstNode::UnaryExpr(n) => (n.children.clone(), n.operator),
458 other => return Err(EvalError::EvalParseError(
459 format!("Internal error: expected UnaryExpr node, found {:?}", other),
460 )),
461 };
462
463 let child_val = self.eval_node(children[0])?;
464 match operator {
465 None => Ok(child_val),
466 Some(UnaryOp::Plus) => {
467 match &child_val {
468 EvalValue::Integer(_) | EvalValue::Float(_) => Ok(child_val),
469 EvalValue::Null => Err(EvalError::NullInOperation {
470 operation: "unary +".to_string(),
471 context: self.input().to_string(),
472 }),
473 _ => Err(EvalError::TypeError {
474 operation: "unary +".to_string(),
475 expected: "numeric".to_string(),
476 actual: child_val.type_name().to_string(),
477 context: self.input().to_string(),
478 }),
479 }
480 }
481 Some(UnaryOp::Negate) => {
482 match &child_val {
483 EvalValue::Integer(i) => Ok(EvalValue::Integer(-i)),
484 EvalValue::Float(f) => Ok(EvalValue::Float(-f)),
485 EvalValue::Null => Err(EvalError::NullInOperation {
486 operation: "unary minus".to_string(),
487 context: self.input().to_string(),
488 }),
489 _ => Err(EvalError::TypeError {
490 operation: "unary minus".to_string(),
491 expected: "numeric".to_string(),
492 actual: child_val.type_name().to_string(),
493 context: self.input().to_string(),
494 }),
495 }
496 }
497 Some(UnaryOp::Not) => {
498 match &child_val {
499 EvalValue::Bool(b) => Ok(EvalValue::Bool(!b)),
500 _ => Err(EvalError::TypeError {
501 operation: "NOT".to_string(),
502 expected: "boolean".to_string(),
503 actual: child_val.type_name().to_string(),
504 context: self.input().to_string(),
505 }),
506 }
507 }
508 }
509 }
510
511 fn eval_primary(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
512 let children = self.get_children(node_id);
513 self.eval_node(children[0])
514 }
515
516 fn eval_literal(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
517 let node = match self.arena().get_node(node_id) {
518 AstNode::Literal(n) => n.clone(),
519 other => return Err(EvalError::EvalParseError(
520 format!("Internal error: expected Literal node, found {:?}", other),
521 )),
522 };
523
524 if !node.children.is_empty() {
525 return self.eval_node(node.children[0]);
527 }
528
529 let token = self.arena().get_token(node.begin_token);
530 let image = &token.image;
531 match token.token_type {
532 TokenType::TRUE => Ok(EvalValue::Bool(true)),
533 TokenType::FALSE => Ok(EvalValue::Bool(false)),
534 TokenType::NULL => Ok(EvalValue::Null),
535 TokenType::FLOATING_POINT_LITERAL => {
536 let f: f64 = image.parse().map_err(|e: std::num::ParseFloatError| {
537 EvalError::InvalidLiteral {
538 literal: image.clone(),
539 literal_type: "float".to_string(),
540 error: e.to_string(),
541 }
542 })?;
543 Ok(EvalValue::Float(f))
544 }
545 TokenType::DECIMAL_LITERAL => {
546 let clean = image.strip_suffix('L').or_else(|| image.strip_suffix('l')).unwrap_or(image);
547 if clean.contains('.') {
548 let f: f64 = clean.parse().map_err(|e: std::num::ParseFloatError| {
549 EvalError::InvalidLiteral {
550 literal: image.clone(),
551 literal_type: "float".to_string(),
552 error: e.to_string(),
553 }
554 })?;
555 Ok(EvalValue::Float(f))
556 } else {
557 let i: i64 = clean.parse().map_err(|e: std::num::ParseIntError| {
558 EvalError::InvalidLiteral {
559 literal: image.clone(),
560 literal_type: "integer".to_string(),
561 error: e.to_string(),
562 }
563 })?;
564 Ok(EvalValue::Integer(i))
565 }
566 }
567 TokenType::HEX_LITERAL => {
568 let clean = image.strip_suffix('L').or_else(|| image.strip_suffix('l')).unwrap_or(image);
569 let hex_str = clean.strip_prefix("0x")
570 .or_else(|| clean.strip_prefix("0X"))
571 .unwrap_or(clean);
572 let i = i64::from_str_radix(hex_str, 16).map_err(|e| {
573 EvalError::InvalidLiteral {
574 literal: image.clone(),
575 literal_type: "hex".to_string(),
576 error: e.to_string(),
577 }
578 })?;
579 Ok(EvalValue::Integer(i))
580 }
581 TokenType::OCTAL_LITERAL => {
582 let clean = image.strip_suffix('L').or_else(|| image.strip_suffix('l')).unwrap_or(image);
583 let oct_str = clean.strip_prefix('0').unwrap_or(clean);
584 let i = i64::from_str_radix(oct_str, 8).map_err(|e| {
585 EvalError::InvalidLiteral {
586 literal: image.clone(),
587 literal_type: "octal".to_string(),
588 error: e.to_string(),
589 }
590 })?;
591 Ok(EvalValue::Integer(i))
592 }
593 _ => Err(EvalError::InvalidLiteral {
594 literal: image.clone(),
595 literal_type: format!("{:?}", token.token_type),
596 error: "unsupported literal type".to_string(),
597 }),
598 }
599 }
600
601 fn eval_string_literal(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
602 let node = match self.arena().get_node(node_id) {
603 AstNode::StringLiteral(n) => n.clone(),
604 other => return Err(EvalError::EvalParseError(
605 format!("Internal error: expected StringLiteral node, found {:?}", other),
606 )),
607 };
608
609 let token = self.arena().get_token(node.begin_token);
610 let image = &token.image;
611 let inner = &image[1..image.len() - 1];
613 Ok(EvalValue::Str(inner.to_string()))
614 }
615
616 fn eval_variable(&self, node_id: NodeId) -> Result<EvalValue, EvalError> {
617 let node = match self.arena().get_node(node_id) {
618 AstNode::Variable(n) => n.clone(),
619 other => return Err(EvalError::EvalParseError(
620 format!("Internal error: expected Variable node, found {:?}", other),
621 )),
622 };
623
624 let token = self.arena().get_token(node.begin_token);
625 let name = &token.image;
626
627 match self.value_map.get(name) {
628 Some(rv) => Ok(EvalValue::from(rv)),
629 None => Err(EvalError::UnboundVariable {
630 name: name.clone(),
631 }),
632 }
633 }
634
635 fn eval_eq_values(&self, left: &EvalValue, right: &EvalValue, op_name: &str) -> Result<EvalValue, EvalError> {
640 match (left, right) {
641 (EvalValue::Null, _) | (_, EvalValue::Null) => {
642 Err(EvalError::NullInOperation {
643 operation: op_name.to_string(),
644 context: self.input().to_string(),
645 })
646 }
647 (EvalValue::Integer(a), EvalValue::Integer(b)) => Ok(EvalValue::Bool(a == b)),
648 (EvalValue::Float(a), EvalValue::Float(b)) => Ok(EvalValue::Bool(a == b)),
649 (EvalValue::Integer(a), EvalValue::Float(b)) => Ok(EvalValue::Bool((*a as f64) == *b)),
650 (EvalValue::Float(a), EvalValue::Integer(b)) => Ok(EvalValue::Bool(*a == (*b as f64))),
651 (EvalValue::Str(a), EvalValue::Str(b)) => Ok(EvalValue::Bool(a == b)),
652 (EvalValue::Bool(a), EvalValue::Bool(b)) => Ok(EvalValue::Bool(a == b)),
653 _ => Err(EvalError::TypeError {
654 operation: op_name.to_string(),
655 expected: left.type_name().to_string(),
656 actual: right.type_name().to_string(),
657 context: self.input().to_string(),
658 }),
659 }
660 }
661
662 fn eval_ordering_comparison(&self, left: &EvalValue, right: &EvalValue, op: ComparisonOp) -> Result<EvalValue, EvalError> {
663 let op_name = match op {
664 ComparisonOp::GreaterThan => "GreaterThan",
665 ComparisonOp::GreaterThanEqual => "GreaterThanEqual",
666 ComparisonOp::LessThan => "LessThan",
667 ComparisonOp::LessThanEqual => "LessThanEqual",
668 other => return Err(EvalError::EvalParseError(
669 format!("Internal error: unexpected operator {:?} in ordering comparison", other),
670 )),
671 };
672
673 match (left, right) {
674 (EvalValue::Null, _) | (_, EvalValue::Null) => {
675 Err(EvalError::NullInOperation {
676 operation: op_name.to_string(),
677 context: self.input().to_string(),
678 })
679 }
680 (EvalValue::Integer(a), EvalValue::Integer(b)) => {
681 Ok(EvalValue::Bool(apply_ordering(*a, *b, op)?))
682 }
683 (EvalValue::Float(a), EvalValue::Float(b)) => {
684 Ok(EvalValue::Bool(apply_ordering_f64(*a, *b, op)?))
685 }
686 (EvalValue::Integer(a), EvalValue::Float(b)) => {
687 Ok(EvalValue::Bool(apply_ordering_f64(*a as f64, *b, op)?))
688 }
689 (EvalValue::Float(a), EvalValue::Integer(b)) => {
690 Ok(EvalValue::Bool(apply_ordering_f64(*a, *b as f64, op)?))
691 }
692 (EvalValue::Str(a), EvalValue::Str(b)) => {
693 Ok(EvalValue::Bool(apply_ordering(a.as_str(), b.as_str(), op)?))
694 }
695 _ => Err(EvalError::TypeError {
696 operation: op_name.to_string(),
697 expected: left.type_name().to_string(),
698 actual: right.type_name().to_string(),
699 context: self.input().to_string(),
700 }),
701 }
702 }
703
704 fn eval_arithmetic_add(&self, left: &EvalValue, right: &EvalValue, op: AddOp) -> Result<EvalValue, EvalError> {
705 let op_name = match op {
706 AddOp::Plus => "addition",
707 AddOp::Minus => "subtraction",
708 };
709
710 match (left, right) {
711 (EvalValue::Null, _) | (_, EvalValue::Null) => {
712 Err(EvalError::NullInOperation {
713 operation: op_name.to_string(),
714 context: self.input().to_string(),
715 })
716 }
717 (EvalValue::Integer(a), EvalValue::Integer(b)) => {
718 match op {
719 AddOp::Plus => Ok(EvalValue::Integer(a + b)),
720 AddOp::Minus => Ok(EvalValue::Integer(a - b)),
721 }
722 }
723 (EvalValue::Float(a), EvalValue::Float(b)) => {
724 match op {
725 AddOp::Plus => Ok(EvalValue::Float(a + b)),
726 AddOp::Minus => Ok(EvalValue::Float(a - b)),
727 }
728 }
729 (EvalValue::Integer(a), EvalValue::Float(b)) => {
730 let a = *a as f64;
731 match op {
732 AddOp::Plus => Ok(EvalValue::Float(a + b)),
733 AddOp::Minus => Ok(EvalValue::Float(a - b)),
734 }
735 }
736 (EvalValue::Float(a), EvalValue::Integer(b)) => {
737 let b = *b as f64;
738 match op {
739 AddOp::Plus => Ok(EvalValue::Float(a + b)),
740 AddOp::Minus => Ok(EvalValue::Float(a - b)),
741 }
742 }
743 _ => Err(EvalError::TypeError {
744 operation: op_name.to_string(),
745 expected: "numeric".to_string(),
746 actual: format!("{} and {}", left.type_name(), right.type_name()),
747 context: self.input().to_string(),
748 }),
749 }
750 }
751
752 fn eval_arithmetic_mult(&self, left: &EvalValue, right: &EvalValue, op: MultExprOp) -> Result<EvalValue, EvalError> {
753 let op_name = match op {
754 MultExprOp::Star => "*",
755 MultExprOp::Slash => "/",
756 MultExprOp::Percent => "%",
757 };
758
759 match (left, right) {
760 (EvalValue::Null, _) | (_, EvalValue::Null) => {
761 Err(EvalError::NullInOperation {
762 operation: op_name.to_string(),
763 context: self.input().to_string(),
764 })
765 }
766 (EvalValue::Integer(a), EvalValue::Integer(b)) => {
767 match op {
768 MultExprOp::Star => Ok(EvalValue::Integer(a * b)),
769 MultExprOp::Slash => {
770 if *b == 0 {
771 return Err(EvalError::DivisionByZero {
772 expression: self.input().to_string(),
773 });
774 }
775 Ok(EvalValue::Float(*a as f64 / *b as f64))
776 }
777 MultExprOp::Percent => {
778 if *b == 0 {
779 return Err(EvalError::DivisionByZero {
780 expression: self.input().to_string(),
781 });
782 }
783 Ok(EvalValue::Integer(a % b))
784 }
785 }
786 }
787 (EvalValue::Float(a), EvalValue::Float(b)) => {
788 match op {
789 MultExprOp::Star => Ok(EvalValue::Float(a * b)),
790 MultExprOp::Slash => {
791 if *b == 0.0 {
792 return Err(EvalError::DivisionByZero {
793 expression: self.input().to_string(),
794 });
795 }
796 Ok(EvalValue::Float(a / b))
797 }
798 MultExprOp::Percent => {
799 if *b == 0.0 {
800 return Err(EvalError::DivisionByZero {
801 expression: self.input().to_string(),
802 });
803 }
804 Ok(EvalValue::Float(a % b))
805 }
806 }
807 }
808 (EvalValue::Integer(a), EvalValue::Float(b)) => {
809 let a = *a as f64;
810 match op {
811 MultExprOp::Star => Ok(EvalValue::Float(a * b)),
812 MultExprOp::Slash => {
813 if *b == 0.0 {
814 return Err(EvalError::DivisionByZero {
815 expression: self.input().to_string(),
816 });
817 }
818 Ok(EvalValue::Float(a / b))
819 }
820 MultExprOp::Percent => {
821 if *b == 0.0 {
822 return Err(EvalError::DivisionByZero {
823 expression: self.input().to_string(),
824 });
825 }
826 Ok(EvalValue::Float(a % b))
827 }
828 }
829 }
830 (EvalValue::Float(a), EvalValue::Integer(b)) => {
831 let b = *b as f64;
832 match op {
833 MultExprOp::Star => Ok(EvalValue::Float(a * b)),
834 MultExprOp::Slash => {
835 if b == 0.0 {
836 return Err(EvalError::DivisionByZero {
837 expression: self.input().to_string(),
838 });
839 }
840 Ok(EvalValue::Float(a / b))
841 }
842 MultExprOp::Percent => {
843 if b == 0.0 {
844 return Err(EvalError::DivisionByZero {
845 expression: self.input().to_string(),
846 });
847 }
848 Ok(EvalValue::Float(a % b))
849 }
850 }
851 }
852 _ => Err(EvalError::TypeError {
853 operation: op_name.to_string(),
854 expected: "numeric".to_string(),
855 actual: format!("{} and {}", left.type_name(), right.type_name()),
856 context: self.input().to_string(),
857 }),
858 }
859 }
860
861 fn eval_between(&self, value: &EvalValue, low: &EvalValue, high: &EvalValue, op: ComparisonOp) -> Result<EvalValue, EvalError> {
862 let between_name = match op {
863 ComparisonOp::Between => "BETWEEN",
864 ComparisonOp::NotBetween => "NOT BETWEEN",
865 other => return Err(EvalError::EvalParseError(
866 format!("Internal error: unexpected operator {:?} in BETWEEN evaluation", other),
867 )),
868 };
869 if matches!(value, EvalValue::Null) || matches!(low, EvalValue::Null) || matches!(high, EvalValue::Null) {
871 return Err(EvalError::NullInOperation {
872 operation: between_name.to_string(),
873 context: self.input().to_string(),
874 });
875 }
876 let ge_low = self.eval_ordering_comparison(value, low, ComparisonOp::GreaterThanEqual)?;
878 let le_high = self.eval_ordering_comparison(value, high, ComparisonOp::LessThanEqual)?;
879
880 let result = match (&ge_low, &le_high) {
881 (EvalValue::Bool(a), EvalValue::Bool(b)) => *a && *b,
882 _ => return Err(EvalError::EvalParseError(
883 format!("Internal error: BETWEEN comparison returned non-boolean results ({}, {})",
884 ge_low.type_name(), le_high.type_name()),
885 )),
886 };
887
888 match op {
889 ComparisonOp::Between => Ok(EvalValue::Bool(result)),
890 ComparisonOp::NotBetween => Ok(EvalValue::Bool(!result)),
891 other => Err(EvalError::EvalParseError(
892 format!("Internal error: unexpected operator {:?} in BETWEEN result", other),
893 )),
894 }
895 }
896
897 fn eval_in(&self, value: &EvalValue, elements: &[EvalValue], op: ComparisonOp) -> Result<EvalValue, EvalError> {
898 if let Some(first) = elements.first()
902 && !matches!(value, EvalValue::Null) && !Self::in_types_compatible(value, first) {
903 return Err(EvalError::TypeError {
904 operation: "IN".to_string(),
905 expected: first.type_name().to_string(),
906 actual: value.type_name().to_string(),
907 context: self.input().to_string(),
908 });
909 }
910 for elem in elements {
911 let eq = self.eval_eq_values(value, elem, "IN")?;
912 if eq == EvalValue::Bool(true) {
913 return match op {
914 ComparisonOp::In => Ok(EvalValue::Bool(true)),
915 ComparisonOp::NotIn => Ok(EvalValue::Bool(false)),
916 other => Err(EvalError::EvalParseError(
917 format!("Internal error: unexpected operator {:?} in IN evaluation", other),
918 )),
919 };
920 }
921 }
922 match op {
923 ComparisonOp::In => Ok(EvalValue::Bool(false)),
924 ComparisonOp::NotIn => Ok(EvalValue::Bool(true)),
925 other => Err(EvalError::EvalParseError(
926 format!("Internal error: unexpected operator {:?} in IN evaluation", other),
927 )),
928 }
929 }
930
931 fn eval_like(&self, value: &EvalValue, pattern: &EvalValue, escape: Option<char>, op: ComparisonOp) -> Result<EvalValue, EvalError> {
932 let op_name = match op {
933 ComparisonOp::Like => "LIKE",
934 ComparisonOp::NotLike => "NOT LIKE",
935 other => return Err(EvalError::EvalParseError(
936 format!("Internal error: unexpected operator {:?} in LIKE evaluation", other),
937 )),
938 };
939
940 match (value, pattern) {
941 (EvalValue::Null, _) | (_, EvalValue::Null) => {
942 Err(EvalError::NullInOperation {
943 operation: op_name.to_string(),
944 context: self.input().to_string(),
945 })
946 }
947 (EvalValue::Str(val), EvalValue::Str(pat)) => {
948 let matched = sql_like_match(val, pat, escape);
949 match op {
950 ComparisonOp::Like => Ok(EvalValue::Bool(matched)),
951 ComparisonOp::NotLike => Ok(EvalValue::Bool(!matched)),
952 other => Err(EvalError::EvalParseError(
953 format!("Internal error: unexpected operator {:?} in LIKE result", other),
954 )),
955 }
956 }
957 _ => Err(EvalError::TypeError {
958 operation: op_name.to_string(),
959 expected: "string".to_string(),
960 actual: format!("{} and {}", value.type_name(), pattern.type_name()),
961 context: self.input().to_string(),
962 }),
963 }
964 }
965
966 fn in_types_compatible(a: &EvalValue, b: &EvalValue) -> bool {
973 matches!((a, b),
974 (EvalValue::Integer(_), EvalValue::Integer(_))
975 | (EvalValue::Float(_), EvalValue::Float(_))
976 | (EvalValue::Integer(_), EvalValue::Float(_))
977 | (EvalValue::Float(_), EvalValue::Integer(_))
978 | (EvalValue::Str(_), EvalValue::Str(_))
979 | (EvalValue::Bool(_), EvalValue::Bool(_))
980 )
981 }
982
983 fn get_children(&self, node_id: NodeId) -> Vec<NodeId> {
984 match self.arena().get_node(node_id) {
985 AstNode::JmsSelector(n) => n.children.clone(),
986 AstNode::OrExpression(n) => n.children.clone(),
987 AstNode::AndExpression(n) => n.children.clone(),
988 AstNode::EqualityExpression(n) => n.children.clone(),
989 AstNode::ComparisonExpression(n) => n.children.clone(),
990 AstNode::AddExpression(n) => n.children.clone(),
991 AstNode::MultExpr(n) => n.children.clone(),
992 AstNode::UnaryExpr(n) => n.children.clone(),
993 AstNode::PrimaryExpr(n) => n.children.clone(),
994 AstNode::Literal(n) => n.children.clone(),
995 AstNode::StringLiteral(n) => n.children.clone(),
996 AstNode::Variable(n) => n.children.clone(),
997 }
998 }
999}
1000
1001fn apply_ordering<T: PartialOrd>(a: T, b: T, op: ComparisonOp) -> Result<bool, EvalError> {
1006 match op {
1007 ComparisonOp::GreaterThan => Ok(a > b),
1008 ComparisonOp::GreaterThanEqual => Ok(a >= b),
1009 ComparisonOp::LessThan => Ok(a < b),
1010 ComparisonOp::LessThanEqual => Ok(a <= b),
1011 other => Err(EvalError::EvalParseError(
1012 format!("Internal error: unexpected operator {:?} in ordering comparison", other),
1013 )),
1014 }
1015}
1016
1017fn apply_ordering_f64(a: f64, b: f64, op: ComparisonOp) -> Result<bool, EvalError> {
1018 match op {
1019 ComparisonOp::GreaterThan => Ok(a > b),
1020 ComparisonOp::GreaterThanEqual => Ok(a >= b),
1021 ComparisonOp::LessThan => Ok(a < b),
1022 ComparisonOp::LessThanEqual => Ok(a <= b),
1023 other => Err(EvalError::EvalParseError(
1024 format!("Internal error: unexpected operator {:?} in ordering comparison", other),
1025 )),
1026 }
1027}
1028
1029#[derive(Debug)]
1034enum PatternElement {
1035 Percent,
1036 Underscore,
1037 Literal(char),
1038}
1039
1040fn sql_like_match(value: &str, pattern: &str, escape: Option<char>) -> bool {
1041 let mut elements = Vec::new();
1043 let mut chars = pattern.chars().peekable();
1044
1045 while let Some(c) = chars.next() {
1046 if Some(c) == escape {
1047 if let Some(next) = chars.next() {
1049 elements.push(PatternElement::Literal(next));
1050 }
1051 } else if c == '%' {
1052 elements.push(PatternElement::Percent);
1053 } else if c == '_' {
1054 elements.push(PatternElement::Underscore);
1055 } else {
1056 elements.push(PatternElement::Literal(c));
1057 }
1058 }
1059
1060 let val_chars: Vec<char> = value.chars().collect();
1062 let n = val_chars.len();
1063 let m = elements.len();
1064
1065 let mut dp = vec![vec![false; m + 1]; n + 1];
1067 dp[0][0] = true;
1068
1069 for j in 1..=m {
1071 if matches!(elements[j - 1], PatternElement::Percent) {
1072 dp[0][j] = dp[0][j - 1];
1073 } else {
1074 break;
1075 }
1076 }
1077
1078 for i in 1..=n {
1079 for j in 1..=m {
1080 match &elements[j - 1] {
1081 PatternElement::Percent => {
1082 dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
1084 }
1085 PatternElement::Underscore => {
1086 dp[i][j] = dp[i - 1][j - 1];
1088 }
1089 PatternElement::Literal(c) => {
1090 dp[i][j] = dp[i - 1][j - 1] && val_chars[i - 1] == *c;
1091 }
1092 }
1093 }
1094 }
1095
1096 dp[n][m]
1097}