use anyhow::bail;
use hamelin_lib::func::defs::{
BooleanEq, BooleanNeq, IntervalEq, IntervalGt, IntervalGte, IntervalLt, IntervalLte,
IntervalNeq, Is, IsNot, NumericEq, NumericGt, NumericGte, NumericLt, NumericLte, NumericNeq,
StringEq, StringNeq, TimestampEq, TimestampGt, TimestampGte, TimestampLt, TimestampLte,
TimestampNeq,
};
use crate::null_propagate;
use crate::registry::EvalRegistry;
use crate::value::{DecimalValue, Value};
pub fn register(registry: &mut EvalRegistry) {
registry.register_eval::<TimestampEq>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
== null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<TimestampNeq>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
!= null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<TimestampLt>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
< null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<TimestampLte>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
<= null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<TimestampGt>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
> null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<TimestampGte>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_timestamp()?
>= null_propagate!(params.take()?).require_timestamp()?,
))
});
registry.register_eval::<IntervalEq>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left == right))
});
registry.register_eval::<IntervalNeq>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left != right))
});
registry.register_eval::<IntervalLt>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left < right))
});
registry.register_eval::<IntervalLte>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left <= right))
});
registry.register_eval::<IntervalGt>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left > right))
});
registry.register_eval::<IntervalGte>(|mut params| {
let left = null_propagate!(params.take()?).require_interval()?;
let right = null_propagate!(params.take()?).require_interval()?;
Ok(Value::Boolean(left >= right))
});
registry.register_eval::<BooleanEq>(|mut params| {
let left = params.take()?;
let right = params.take()?;
match (left, right) {
(Value::Boolean(l), Value::Boolean(r)) => Ok(Value::Boolean(l == r)),
(Value::Null, _) | (_, Value::Null) => Ok(Value::Null),
_ => bail!("Invalid operands for boolean operation"),
}
});
registry.register_eval::<BooleanNeq>(|mut params| {
let left = params.take()?;
let right = params.take()?;
match (left, right) {
(Value::Boolean(l), Value::Boolean(r)) => Ok(Value::Boolean(l != r)),
(Value::Null, _) | (_, Value::Null) => Ok(Value::Null),
_ => bail!("Invalid operands for boolean operation"),
}
});
registry.register_eval::<StringEq>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_string()?
== null_propagate!(params.take()?).require_string()?,
))
});
registry.register_eval::<StringNeq>(|mut params| {
Ok(Value::Boolean(
null_propagate!(params.take()?).require_string()?
!= null_propagate!(params.take()?).require_string()?,
))
});
registry.register_eval::<NumericEq>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = match (left, right) {
(Value::Int(l), Value::Int(r)) => l == r,
(Value::Double(l), Value::Double(r)) => l == r,
(Value::Int(l), Value::Double(r)) => l as f64 == r,
(Value::Double(l), Value::Int(r)) => l == r as f64,
(Value::Decimal(l), Value::Decimal(r)) => l.eq(&r),
(Value::Decimal(l), Value::Int(r)) => l.eq(&r.into()),
(Value::Int(l), Value::Decimal(r)) => DecimalValue::from(l).eq(&r),
(Value::Decimal(l), Value::Double(r)) => DecimalValue::from(r).eq(&l),
(Value::Double(l), Value::Decimal(r)) => DecimalValue::from(l).eq(&r),
_ => bail!("Invalid operands for numeric comparison"),
};
Ok(Value::Boolean(result))
});
registry.register_eval::<NumericNeq>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = match (left, right) {
(Value::Int(l), Value::Int(r)) => l != r,
(Value::Double(l), Value::Double(r)) => l != r,
(Value::Int(l), Value::Double(r)) => l as f64 != r,
(Value::Double(l), Value::Int(r)) => l != r as f64,
(Value::Decimal(l), Value::Decimal(r)) => !l.eq(&r),
(Value::Decimal(l), Value::Int(r)) => !l.eq(&r.into()),
(Value::Int(l), Value::Decimal(r)) => !DecimalValue::from(l).eq(&r),
(Value::Decimal(l), Value::Double(r)) => !DecimalValue::from(r).eq(&l),
(Value::Double(l), Value::Decimal(r)) => !DecimalValue::from(l).eq(&r),
_ => bail!("Invalid operands for numeric comparison"),
};
Ok(Value::Boolean(result))
});
registry.register_eval::<NumericLt>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = left.lt(&right);
Ok(Value::Boolean(result))
});
registry.register_eval::<NumericLte>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = left.lte(&right);
Ok(Value::Boolean(result))
});
registry.register_eval::<NumericGt>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = left.gt(&right);
Ok(Value::Boolean(result))
});
registry.register_eval::<NumericGte>(|mut params| {
let left = null_propagate!(params.take()?);
let right = null_propagate!(params.take()?);
let result = left.gte(&right);
Ok(Value::Boolean(result))
});
registry.register_eval::<Is>(|mut params| {
let left = params.take()?;
let right = params.take()?;
match right {
Value::Null | Value::Unknown => {
let is_null = matches!(left, Value::Null);
Ok(Value::Boolean(is_null))
}
_ => bail!("IS operator can only be used with NULL"),
}
});
registry.register_eval::<IsNot>(|mut params| {
let left = params.take()?;
let right = params.take()?;
match right {
Value::Null | Value::Unknown => {
let is_null = matches!(left, Value::Null);
Ok(Value::Boolean(!is_null))
}
_ => bail!("IS NOT operator can only be used with NULL"),
}
});
}