pub use super::{combined_core::CombinedExpressionEvaluator, single::ExpressionEvaluator};
use crate::errors::ExecutorError;
pub(crate) fn eval_binary_op_static(
left: &vibesql_types::SqlValue,
op: &vibesql_ast::BinaryOperator,
right: &vibesql_types::SqlValue,
sql_mode: vibesql_types::SqlMode,
) -> Result<vibesql_types::SqlValue, ExecutorError> {
super::operators::OperatorRegistry::eval_binary_op(left, op, right, sql_mode)
}
pub(crate) fn eval_between_static(
expr_val: &vibesql_types::SqlValue,
low_val: &vibesql_types::SqlValue,
high_val: &vibesql_types::SqlValue,
negated: bool,
symmetric: bool,
sql_mode: vibesql_types::SqlMode,
) -> Result<vibesql_types::SqlValue, ExecutorError> {
let mut low = low_val.clone();
let mut high = high_val.clone();
let gt_result = eval_binary_op_static(
&low,
&vibesql_ast::BinaryOperator::GreaterThan,
&high,
sql_mode.clone(),
)?;
if let vibesql_types::SqlValue::Boolean(true) = gt_result {
if symmetric {
std::mem::swap(&mut low, &mut high);
} else {
if matches!(expr_val, vibesql_types::SqlValue::Null) {
return Ok(vibesql_types::SqlValue::Null);
}
return Ok(vibesql_types::SqlValue::Boolean(negated));
}
}
let ge_low = eval_binary_op_static(
expr_val,
&vibesql_ast::BinaryOperator::GreaterThanOrEqual,
&low,
sql_mode.clone(),
)?;
let le_high = eval_binary_op_static(
expr_val,
&vibesql_ast::BinaryOperator::LessThanOrEqual,
&high,
sql_mode.clone(),
)?;
if negated {
let lt_low = eval_binary_op_static(
expr_val,
&vibesql_ast::BinaryOperator::LessThan,
&low,
sql_mode.clone(),
)?;
let gt_high = eval_binary_op_static(
expr_val,
&vibesql_ast::BinaryOperator::GreaterThan,
&high,
sql_mode.clone(),
)?;
eval_binary_op_static(<_low, &vibesql_ast::BinaryOperator::Or, >_high, sql_mode)
} else {
eval_binary_op_static(&ge_low, &vibesql_ast::BinaryOperator::And, &le_high, sql_mode)
}
}
pub(crate) fn values_are_equal(
left: &vibesql_types::SqlValue,
right: &vibesql_types::SqlValue,
) -> bool {
use vibesql_types::SqlValue::*;
match (left, right) {
(Null, _) | (_, Null) => false,
(Integer(a), Integer(b)) => a == b,
(Varchar(a), Varchar(b)) => a == b,
(Character(a), Character(b)) => a == b,
(Character(a), Varchar(b)) | (Varchar(a), Character(b)) => a == b,
(Boolean(a), Boolean(b)) => a == b,
(Boolean(b), Integer(i)) | (Integer(i), Boolean(b)) => {
if *b {
*i == 1
} else {
*i == 0
}
}
(Boolean(b), Bigint(i)) | (Bigint(i), Boolean(b)) => {
if *b {
*i == 1
} else {
*i == 0
}
}
(Boolean(b), Smallint(i)) | (Smallint(i), Boolean(b)) => {
if *b {
*i == 1
} else {
*i == 0
}
}
(
Integer(_) | Smallint(_) | Bigint(_) | Unsigned(_) | Numeric(_) | Float(_) | Real(_)
| Double(_),
Integer(_) | Smallint(_) | Bigint(_) | Unsigned(_) | Numeric(_) | Float(_) | Real(_)
| Double(_),
) => {
match (
crate::evaluator::casting::to_f64(left),
crate::evaluator::casting::to_f64(right),
) {
(Ok(a), Ok(b)) => (a - b).abs() < f64::EPSILON,
_ => false,
}
}
(
Integer(_) | Smallint(_) | Bigint(_) | Unsigned(_) | Numeric(_) | Float(_) | Real(_)
| Double(_),
Varchar(s) | Character(s),
) => {
if let Ok(text_f64) = s.trim().parse::<f64>() {
match crate::evaluator::casting::to_f64(left) {
Ok(num_f64) => (num_f64 - text_f64).abs() < f64::EPSILON,
_ => false,
}
} else {
false }
}
(
Varchar(s) | Character(s),
Integer(_) | Smallint(_) | Bigint(_) | Unsigned(_) | Numeric(_) | Float(_) | Real(_)
| Double(_),
) => {
if let Ok(text_f64) = s.trim().parse::<f64>() {
match crate::evaluator::casting::to_f64(right) {
Ok(num_f64) => (text_f64 - num_f64).abs() < f64::EPSILON,
_ => false,
}
} else {
false }
}
_ => false, }
}
pub(crate) fn values_are_distinct(
left: &vibesql_types::SqlValue,
right: &vibesql_types::SqlValue,
) -> bool {
use vibesql_types::SqlValue::*;
match (left, right) {
(Null, Null) => false,
(Null, _) | (_, Null) => true,
_ => !values_are_equal(left, right),
}
}