use sea_query::{Alias, Expr as SqExpr};
use super::Predicate;
pub struct F;
impl F {
pub fn col(name: impl Into<String>) -> FExpr {
FExpr {
inner: FExprInner::Column(name.into()),
}
}
}
#[derive(Clone, Debug)]
enum FExprInner {
Column(String),
Add(Box<FExpr>, Box<FExpr>),
Sub(Box<FExpr>, Box<FExpr>),
Mul(Box<FExpr>, Box<FExpr>),
Div(Box<FExpr>, Box<FExpr>),
LitI64(i64),
}
#[derive(Clone, Debug)]
pub struct FExpr {
inner: FExprInner,
}
impl FExpr {
pub(crate) fn to_simple_expr(&self) -> sea_query::SimpleExpr {
match &self.inner {
FExprInner::Column(name) => SqExpr::col(Alias::new(name.as_str())).into(),
FExprInner::Add(lhs, rhs) => {
let l = lhs.to_simple_expr();
let r = rhs.to_simple_expr();
l.add(r)
}
FExprInner::Sub(lhs, rhs) => {
let l = lhs.to_simple_expr();
let r = rhs.to_simple_expr();
l.sub(r)
}
FExprInner::Mul(lhs, rhs) => {
let l = lhs.to_simple_expr();
let r = rhs.to_simple_expr();
l.mul(r)
}
FExprInner::Div(lhs, rhs) => {
let l = lhs.to_simple_expr();
let r = rhs.to_simple_expr();
l.div(r)
}
FExprInner::LitI64(n) => {
sea_query::SimpleExpr::Value(sea_query::Value::BigInt(Some(*n)))
}
}
}
#[allow(clippy::should_implement_trait)]
pub fn add(self, n: i64) -> FExpr {
FExpr {
inner: FExprInner::Add(Box::new(self), Box::new(FExpr::lit_i64(n))),
}
}
#[allow(clippy::should_implement_trait)]
pub fn sub(self, n: i64) -> FExpr {
FExpr {
inner: FExprInner::Sub(Box::new(self), Box::new(FExpr::lit_i64(n))),
}
}
#[allow(clippy::should_implement_trait)]
pub fn mul(self, n: i64) -> FExpr {
FExpr {
inner: FExprInner::Mul(Box::new(self), Box::new(FExpr::lit_i64(n))),
}
}
#[allow(clippy::should_implement_trait)]
pub fn div(self, n: i64) -> FExpr {
FExpr {
inner: FExprInner::Div(Box::new(self), Box::new(FExpr::lit_i64(n))),
}
}
fn lit_i64(n: i64) -> FExpr {
FExpr {
inner: FExprInner::LitI64(n),
}
}
}
pub trait FColExt<T> {
fn eq_f(&self, expr: FExpr) -> Predicate<T>;
fn ne_f(&self, expr: FExpr) -> Predicate<T>;
}
impl<T> FColExt<T> for crate::orm::column::IntCol<T> {
fn eq_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).eq(expr.to_simple_expr()))
}
fn ne_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).ne(expr.to_simple_expr()))
}
}
impl<T> FColExt<T> for crate::orm::column::ForeignKeyCol<T> {
fn eq_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).eq(expr.to_simple_expr()))
}
fn ne_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).ne(expr.to_simple_expr()))
}
}
impl<T> FColExt<T> for crate::orm::column::StrCol<T> {
fn eq_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).eq(expr.to_simple_expr()))
}
fn ne_f(&self, expr: FExpr) -> Predicate<T> {
Predicate::new(SqExpr::col(Alias::new(self.name)).ne(expr.to_simple_expr()))
}
}
pub struct Q;
impl Q {
pub fn and<T>(a: Predicate<T>, b: Predicate<T>) -> Predicate<T> {
a & b
}
pub fn or<T>(a: Predicate<T>, b: Predicate<T>) -> Predicate<T> {
a | b
}
pub fn not<T>(p: Predicate<T>) -> Predicate<T> {
use std::marker::PhantomData;
let negated_cond = p.cond.not();
let negated_sqlite = p.cond_sqlite.map(|c| c.not());
Predicate {
cond: negated_cond,
cond_sqlite: negated_sqlite,
_phantom: PhantomData,
}
}
}