use vantage_expressions::traits::expressive::ExpressiveEnum;
use vantage_expressions::{Expression, Expressive};
use crate::primitives::fx::Fx;
use crate::primitives::identifier::Identifier;
macro_rules! define_sql_condition {
($name:ident, $any_type:ty) => {
#[derive(Debug, Clone)]
pub struct $name(pub Expression<$any_type>);
impl $name {
pub fn into_expr(self) -> Expression<$any_type> {
self.0
}
pub fn from_typed<F>(expr: Expression<F>) -> Self
where
F: Into<$any_type> + Send + Clone + 'static,
{
use vantage_expressions::ExpressionMap;
Self(expr.map())
}
}
impl<F> From<Expression<F>> for $name
where
F: Into<$any_type> + Send + Clone + 'static,
{
fn from(expr: Expression<F>) -> Self {
Self::from_typed(expr)
}
}
impl From<Identifier> for $name {
fn from(id: Identifier) -> Self {
use vantage_expressions::Expressive;
Self(id.expr())
}
}
impl From<$name> for Expression<$any_type> {
fn from(cond: $name) -> Self {
cond.0
}
}
impl From<Fx<$any_type>> for $name {
fn from(fx: Fx<$any_type>) -> Self {
Self(fx.into())
}
}
};
}
#[cfg(feature = "sqlite")]
define_sql_condition!(SqliteCondition, crate::sqlite::types::AnySqliteType);
#[cfg(feature = "postgres")]
define_sql_condition!(PostgresCondition, crate::postgres::types::AnyPostgresType);
#[cfg(feature = "mysql")]
define_sql_condition!(MysqlCondition, crate::mysql::types::AnyMysqlType);
#[cfg(feature = "mysql")]
impl From<crate::mysql::statements::primitives::FulltextMatch> for MysqlCondition {
fn from(fm: crate::mysql::statements::primitives::FulltextMatch) -> Self {
Self(fm.into())
}
}
#[macro_export]
macro_rules! define_typed_ident {
($struct_name:ident, $fn_name:ident, $any_type:ty, $condition:ty) => {
#[derive(Debug, Clone)]
pub struct $struct_name($crate::primitives::identifier::Identifier);
impl $struct_name {
pub fn new(name: impl Into<String>) -> Self {
Self($crate::primitives::identifier::ident(name))
}
pub fn dot_of(mut self, prefix: impl Into<String>) -> Self {
self.0 = self.0.dot_of(prefix);
self
}
pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
self.0 = self.0.with_alias(alias);
self
}
}
impl $crate::vantage_expressions::Expressive<$any_type> for $struct_name {
fn expr(&self) -> $crate::vantage_expressions::Expression<$any_type> {
$crate::vantage_expressions::Expressive::<$any_type>::expr(&self.0)
}
}
impl From<$struct_name> for $crate::vantage_expressions::Expression<$any_type> {
fn from(id: $struct_name) -> Self {
$crate::vantage_expressions::Expressive::<$any_type>::expr(&id.0)
}
}
impl From<$struct_name> for $condition {
fn from(id: $struct_name) -> Self {
Self::from_typed($crate::vantage_expressions::Expressive::<$any_type>::expr(
&id.0,
))
}
}
pub fn $fn_name(name: impl Into<String>) -> $struct_name {
$struct_name::new(name)
}
};
}
#[macro_export]
macro_rules! define_sql_operation {
($trait_name:ident, $condition:ident, $any_type:ty) => {
pub trait $trait_name<T>: $crate::vantage_expressions::Expressive<T>
where
T: Into<$any_type> + Send + Clone + 'static,
{
fn eq(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} = {}",
)
}
fn ne(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} != {}",
)
}
fn gt(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} > {}",
)
}
fn gte(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} >= {}",
)
}
fn lt(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} < {}",
)
}
fn lte(&self, value: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self, value, "{} <= {}",
)
}
fn in_(&self, values: impl $crate::vantage_expressions::Expressive<T>) -> $condition
where
Self: Sized,
{
$crate::condition::build_sql_binary::<T, $any_type, $condition>(
self,
values,
"{} IN ({})",
)
}
fn in_list<V: Into<T> + Clone>(&self, values: &[V]) -> $condition
where
Self: Sized,
T: Clone,
{
use $crate::vantage_expressions::Expression;
use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
let params: Vec<Expression<T>> = values
.iter()
.map(|v| Expression::new("{}", vec![ExpressiveEnum::Scalar(v.clone().into())]))
.collect();
let expr: Expression<T> = Expression::new(
"{} IN ({})",
vec![
ExpressiveEnum::Nested(self.expr()),
ExpressiveEnum::Nested(Expression::from_vec(params, ", ")),
],
);
$condition::from_typed(expr)
}
fn cast(&self, type_name: &str) -> $condition
where
Self: Sized,
{
use $crate::vantage_expressions::Expression;
use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
let expr: Expression<T> = Expression::new(
format!("CAST({{}} AS {type_name})"),
vec![ExpressiveEnum::Nested(self.expr())],
);
$condition::from_typed(expr)
}
fn is_null(&self) -> $condition
where
Self: Sized,
{
use $crate::vantage_expressions::Expression;
use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
let expr: Expression<T> =
Expression::new("{} IS NULL", vec![ExpressiveEnum::Nested(self.expr())]);
$condition::from_typed(expr)
}
fn is_not_null(&self) -> $condition
where
Self: Sized,
{
use $crate::vantage_expressions::Expression;
use $crate::vantage_expressions::traits::expressive::ExpressiveEnum;
let expr: Expression<T> =
Expression::new("{} IS NOT NULL", vec![ExpressiveEnum::Nested(self.expr())]);
$condition::from_typed(expr)
}
}
impl<T, S> $trait_name<T> for S
where
S: $crate::vantage_expressions::Expressive<T>,
T: Into<$any_type> + Send + Clone + 'static,
{
}
impl $crate::vantage_expressions::Expressive<$any_type> for $condition {
fn expr(&self) -> $crate::vantage_expressions::Expression<$any_type> {
self.0.clone()
}
}
};
}
pub fn build_sql_binary<T, AnyType, Cond>(
lhs: &(impl Expressive<T> + ?Sized),
rhs: impl Expressive<T>,
template: &str,
) -> Cond
where
T: Into<AnyType> + Send + Clone + 'static,
Cond: From<Expression<T>>,
{
let expr: Expression<T> = Expression::new(
template,
vec![
ExpressiveEnum::Nested(lhs.expr()),
ExpressiveEnum::Nested(rhs.expr()),
],
);
Cond::from(expr)
}