use crate::condition::MysqlCondition;
use crate::define_sql_operation;
define_sql_operation!(
MysqlOperation,
MysqlCondition,
crate::mysql::types::AnyMysqlType
);
use vantage_expressions::{Expression, Expressive, ExpressiveEnum};
use super::types::AnyMysqlType;
type Expr = Expression<AnyMysqlType>;
pub trait MysqlExt: Expressive<AnyMysqlType> {
fn regexp(&self, pattern: impl Expressive<AnyMysqlType>) -> Expr {
Expression::new(
"{} REGEXP {}",
vec![
ExpressiveEnum::Nested(self.expr()),
ExpressiveEnum::Nested(pattern.expr()),
],
)
}
fn bitand(&self, other: impl Expressive<AnyMysqlType>) -> Expr {
Expression::new(
"{} & {}",
vec![
ExpressiveEnum::Nested(self.expr()),
ExpressiveEnum::Nested(other.expr()),
],
)
}
fn bitor(&self, other: impl Expressive<AnyMysqlType>) -> Expr {
Expression::new(
"{} | {}",
vec![
ExpressiveEnum::Nested(self.expr()),
ExpressiveEnum::Nested(other.expr()),
],
)
}
}
impl<T: Expressive<AnyMysqlType>> MysqlExt for T {}
#[cfg(test)]
mod tests {
use super::*;
use vantage_table::column::core::Column;
#[test]
fn test_column_eq() {
let name = Column::<AnyMysqlType>::new("name");
let cond = name.eq(AnyMysqlType::from("Alice".to_string()));
assert_eq!(cond.into_expr().preview(), "name = 'Alice'");
}
#[test]
fn test_typed_column_gt() {
let price = Column::<i64>::new("price");
let cond = price.gt(150i64);
assert_eq!(cond.into_expr().preview(), "price > 150");
}
#[test]
fn test_chaining_gt_eq_false() {
let price = Column::<i64>::new("price");
let cond = price.gt(10i64).eq(false);
assert_eq!(cond.into_expr().preview(), "price > 10 = false");
}
#[test]
fn test_chaining_gt_eq_true() {
let price = Column::<i64>::new("price");
let cond = price.gt(10i64).eq(true);
assert_eq!(cond.into_expr().preview(), "price > 10 = true");
}
#[test]
fn test_typed_bool_column() {
let is_deleted = Column::<bool>::new("is_deleted");
let cond = is_deleted.eq(false);
assert_eq!(cond.into_expr().preview(), "is_deleted = false");
}
#[test]
fn test_cross_type_rejected() {
let price = Column::<i64>::new("price");
let _: MysqlCondition = price.gt(150i64);
}
#[test]
fn test_is_null() {
let deleted_at = Column::<String>::new("deleted_at");
let cond = deleted_at.is_null();
assert_eq!(cond.into_expr().preview(), "deleted_at IS NULL");
}
#[test]
fn test_is_not_null() {
let email = Column::<String>::new("email");
let cond = email.is_not_null();
assert_eq!(cond.into_expr().preview(), "email IS NOT NULL");
}
}