use crate::{
db::predicate::{
CoercionSpec, CompareOp, TextOp, compare_eq, compare_order, compare_text,
eval_equality_compare_result, eval_list_membership_compare_result,
eval_ordered_compare_result,
},
value::Value,
};
pub(in crate::db) fn eval_compare_values(
actual: &Value,
op: CompareOp,
value: &Value,
coercion: &CoercionSpec,
) -> bool {
match op {
CompareOp::Eq | CompareOp::Ne => {
eval_equality_compare_result(op, compare_eq(actual, value, coercion))
}
CompareOp::Lt | CompareOp::Lte | CompareOp::Gt | CompareOp::Gte => {
compare_order(actual, value, coercion)
.is_some_and(|ordering| eval_ordered_compare_result(op, ordering))
}
CompareOp::In | CompareOp::NotIn => {
eval_list_membership_compare_result(op, in_list(actual, value, coercion))
}
CompareOp::Contains => contains(actual, value, coercion),
CompareOp::StartsWith => {
compare_text(actual, value, coercion, TextOp::StartsWith).unwrap_or(false)
}
CompareOp::EndsWith => {
compare_text(actual, value, coercion, TextOp::EndsWith).unwrap_or(false)
}
}
}
pub(in crate::db::predicate::runtime) const fn is_empty_value(value: &Value) -> bool {
match value {
Value::Text(text) => text.is_empty(),
Value::List(items) => items.is_empty(),
_ => false,
}
}
fn in_list(actual: &Value, list: &Value, coercion: &CoercionSpec) -> Option<bool> {
let Value::List(items) = list else {
return None;
};
let mut saw_valid = false;
for item in items {
match compare_eq(actual, item, coercion) {
Some(true) => return Some(true),
Some(false) => saw_valid = true,
None => {}
}
}
saw_valid.then_some(false)
}
fn contains(actual: &Value, needle: &Value, coercion: &CoercionSpec) -> bool {
if matches!(actual, Value::Text(_)) {
return false;
}
let Value::List(items) = actual else {
return false;
};
items
.iter()
.any(|item| compare_eq(item, needle, coercion).unwrap_or(false))
}