#[derive(Debug, Clone, PartialEq)]
pub enum JoinValue {
Null,
Boolean(bool),
Integer(i64),
Float(f64),
String(String),
}
impl JoinValue {
pub fn is_null(&self) -> bool {
matches!(self, JoinValue::Null)
}
pub fn to_hash_key(&self) -> String {
match self {
JoinValue::Null => "__NULL__".to_string(),
JoinValue::Boolean(b) => format!("b:{}", b),
JoinValue::Integer(i) => format!("i:{}", i),
JoinValue::Float(f) => format!("f:{:?}", f),
JoinValue::String(s) => format!("s:{}", s),
}
}
pub fn equals(&self, other: &JoinValue) -> Option<bool> {
if self.is_null() || other.is_null() {
return None; }
match (self, other) {
(JoinValue::Boolean(a), JoinValue::Boolean(b)) => Some(a == b),
(JoinValue::Integer(a), JoinValue::Integer(b)) => Some(a == b),
(JoinValue::Integer(a), JoinValue::Float(b)) => Some((*a as f64) == *b),
(JoinValue::Float(a), JoinValue::Integer(b)) => Some(*a == (*b as f64)),
(JoinValue::Float(a), JoinValue::Float(b)) => Some(a == b),
(JoinValue::String(a), JoinValue::String(b)) => Some(a == b),
_ => Some(false), }
}
pub fn compare(&self, other: &JoinValue) -> Option<std::cmp::Ordering> {
if self.is_null() || other.is_null() {
return None;
}
match (self, other) {
(JoinValue::Boolean(a), JoinValue::Boolean(b)) => Some(a.cmp(b)),
(JoinValue::Integer(a), JoinValue::Integer(b)) => Some(a.cmp(b)),
(JoinValue::Integer(a), JoinValue::Float(b)) => (*a as f64).partial_cmp(b),
(JoinValue::Float(a), JoinValue::Integer(b)) => a.partial_cmp(&(*b as f64)),
(JoinValue::Float(a), JoinValue::Float(b)) => a.partial_cmp(b),
(JoinValue::String(a), JoinValue::String(b)) => Some(a.cmp(b)),
_ => None, }
}
pub fn negate(&self) -> Option<JoinValue> {
match self {
JoinValue::Integer(i) => Some(JoinValue::Integer(-i)),
JoinValue::Float(f) => Some(JoinValue::Float(-f)),
_ => None,
}
}
pub fn not(&self) -> Option<JoinValue> {
match self {
JoinValue::Boolean(b) => Some(JoinValue::Boolean(!b)),
_ => None,
}
}
pub fn add(&self, other: &JoinValue) -> Option<JoinValue> {
match (self, other) {
(JoinValue::Integer(a), JoinValue::Integer(b)) => {
a.checked_add(*b).map(JoinValue::Integer)
}
(JoinValue::Integer(a), JoinValue::Float(b)) => Some(JoinValue::Float(*a as f64 + b)),
(JoinValue::Float(a), JoinValue::Integer(b)) => Some(JoinValue::Float(a + *b as f64)),
(JoinValue::Float(a), JoinValue::Float(b)) => Some(JoinValue::Float(a + b)),
(JoinValue::String(a), JoinValue::String(b)) => {
Some(JoinValue::String(format!("{}{}", a, b)))
}
_ => None,
}
}
pub fn subtract(&self, other: &JoinValue) -> Option<JoinValue> {
match (self, other) {
(JoinValue::Integer(a), JoinValue::Integer(b)) => {
a.checked_sub(*b).map(JoinValue::Integer)
}
(JoinValue::Integer(a), JoinValue::Float(b)) => Some(JoinValue::Float(*a as f64 - b)),
(JoinValue::Float(a), JoinValue::Integer(b)) => Some(JoinValue::Float(a - *b as f64)),
(JoinValue::Float(a), JoinValue::Float(b)) => Some(JoinValue::Float(a - b)),
_ => None,
}
}
pub fn multiply(&self, other: &JoinValue) -> Option<JoinValue> {
match (self, other) {
(JoinValue::Integer(a), JoinValue::Integer(b)) => {
a.checked_mul(*b).map(JoinValue::Integer)
}
(JoinValue::Integer(a), JoinValue::Float(b)) => Some(JoinValue::Float(*a as f64 * b)),
(JoinValue::Float(a), JoinValue::Integer(b)) => Some(JoinValue::Float(a * *b as f64)),
(JoinValue::Float(a), JoinValue::Float(b)) => Some(JoinValue::Float(a * b)),
_ => None,
}
}
pub fn divide(&self, other: &JoinValue) -> Option<JoinValue> {
match (self, other) {
(JoinValue::Integer(a), JoinValue::Integer(b)) if *b != 0 => {
Some(JoinValue::Integer(a / b))
}
(JoinValue::Integer(a), JoinValue::Float(b)) if *b != 0.0 => {
Some(JoinValue::Float(*a as f64 / b))
}
(JoinValue::Float(a), JoinValue::Integer(b)) if *b != 0 => {
Some(JoinValue::Float(a / *b as f64))
}
(JoinValue::Float(a), JoinValue::Float(b)) if *b != 0.0 => {
Some(JoinValue::Float(a / b))
}
_ => None,
}
}
pub fn modulo(&self, other: &JoinValue) -> Option<JoinValue> {
match (self, other) {
(JoinValue::Integer(a), JoinValue::Integer(b)) if *b != 0 => {
Some(JoinValue::Integer(a % b))
}
(JoinValue::Integer(a), JoinValue::Float(b)) if *b != 0.0 => {
Some(JoinValue::Float(*a as f64 % b))
}
(JoinValue::Float(a), JoinValue::Integer(b)) if *b != 0 => {
Some(JoinValue::Float(a % *b as f64))
}
(JoinValue::Float(a), JoinValue::Float(b)) if *b != 0.0 => {
Some(JoinValue::Float(a % b))
}
_ => None,
}
}
pub fn to_bool(&self) -> Option<bool> {
match self {
JoinValue::Boolean(b) => Some(*b),
JoinValue::Null => None,
_ => None,
}
}
pub fn matches_like(&self, pattern: &JoinValue) -> Option<bool> {
match (self, pattern) {
(JoinValue::String(s), JoinValue::String(p)) => Some(Self::like_match(s, p)),
_ => None,
}
}
pub fn matches_ilike(&self, pattern: &JoinValue) -> Option<bool> {
match (self, pattern) {
(JoinValue::String(s), JoinValue::String(p)) => {
Some(crate::executor::like::like_match(s, p, true))
}
_ => None,
}
}
pub fn like_match(text: &str, pattern: &str) -> bool {
crate::executor::like::like_match(text, pattern, false)
}
}