use std::marker::PhantomData;
use sea_query::{Alias, Expr, ExprTrait, Func};
use super::{OrderExpr, Predicate};
pub struct IntCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> IntCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: i64) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: i64) -> Predicate<T> {
self.ge(val)
}
pub fn in_(&self, vals: &[i64]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn in_subquery(&self, sub: super::Subquery) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).in_subquery(sub.into_statement()))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct StrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> StrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq<S: Into<String>>(&self, val: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val.into()))
}
pub fn ne<S: Into<String>>(&self, val: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val.into()))
}
pub fn like<S: Into<String>>(&self, pattern: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).like(pattern.into()))
}
pub fn ilike<S: Into<String>>(&self, pattern: S) -> Predicate<T> {
let pattern = pattern.into().to_uppercase();
Predicate::new(Expr::expr(Func::upper(Expr::col(Alias::new(self.name)))).like(pattern))
}
pub fn contains<S: Into<String>>(&self, substring: S) -> Predicate<T> {
let pattern = format!("%{}%", super::escape_like_literal(&substring.into()));
Predicate::new(
Expr::col(Alias::new(self.name)).like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn icontains<S: Into<String>>(&self, substring: S) -> Predicate<T> {
let pattern = format!("%{}%", super::escape_like_literal(&substring.into())).to_uppercase();
Predicate::new(
Expr::expr(Func::upper(Expr::col(Alias::new(self.name))))
.like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn startswith<S: Into<String>>(&self, prefix: S) -> Predicate<T> {
let pattern = format!("{}%", super::escape_like_literal(&prefix.into()));
Predicate::new(
Expr::col(Alias::new(self.name)).like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn istartswith<S: Into<String>>(&self, prefix: S) -> Predicate<T> {
let pattern = format!("{}%", super::escape_like_literal(&prefix.into())).to_uppercase();
Predicate::new(
Expr::expr(Func::upper(Expr::col(Alias::new(self.name))))
.like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct DateTimeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> DateTimeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.gt(val)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableDateTimeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableDateTimeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::DateTime<chrono::Utc>) -> Predicate<T> {
self.gt(val)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct F64Col<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> F64Col<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: f64) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: f64) -> Predicate<T> {
self.ge(val)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct BoolCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> BoolCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: bool) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: bool) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn is_true(&self) -> Predicate<T> {
self.eq(true)
}
pub fn is_false(&self) -> Predicate<T> {
self.eq(false)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct UuidCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> UuidCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: uuid::Uuid) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: uuid::Uuid) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn in_(&self, vals: &[uuid::Uuid]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct DateCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> DateCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.gt(val)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct TimeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> TimeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.gt(val)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableIntCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableIntCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: i64) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: i64) -> Predicate<T> {
self.ge(val)
}
pub fn in_(&self, vals: &[i64]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableStrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableStrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq<S: Into<String>>(&self, val: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val.into()))
}
pub fn ne<S: Into<String>>(&self, val: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val.into()))
}
pub fn like<S: Into<String>>(&self, pattern: S) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).like(pattern.into()))
}
pub fn ilike<S: Into<String>>(&self, pattern: S) -> Predicate<T> {
let pattern = pattern.into().to_uppercase();
Predicate::new(Expr::expr(Func::upper(Expr::col(Alias::new(self.name)))).like(pattern))
}
pub fn contains<S: Into<String>>(&self, substring: S) -> Predicate<T> {
let pattern = format!("%{}%", super::escape_like_literal(&substring.into()));
Predicate::new(
Expr::col(Alias::new(self.name)).like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn icontains<S: Into<String>>(&self, substring: S) -> Predicate<T> {
let pattern = format!("%{}%", super::escape_like_literal(&substring.into())).to_uppercase();
Predicate::new(
Expr::expr(Func::upper(Expr::col(Alias::new(self.name))))
.like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn startswith<S: Into<String>>(&self, prefix: S) -> Predicate<T> {
let pattern = format!("{}%", super::escape_like_literal(&prefix.into()));
Predicate::new(
Expr::col(Alias::new(self.name)).like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn istartswith<S: Into<String>>(&self, prefix: S) -> Predicate<T> {
let pattern = format!("{}%", super::escape_like_literal(&prefix.into())).to_uppercase();
Predicate::new(
Expr::expr(Func::upper(Expr::col(Alias::new(self.name))))
.like(sea_query::LikeExpr::new(pattern).escape('\\')),
)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableF64Col<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableF64Col<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: f64) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: f64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: f64) -> Predicate<T> {
self.ge(val)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableBoolCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableBoolCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: bool) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: bool) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn is_true(&self) -> Predicate<T> {
self.eq(true)
}
pub fn is_false(&self) -> Predicate<T> {
self.eq(false)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableUuidCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableUuidCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: uuid::Uuid) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: uuid::Uuid) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn in_(&self, vals: &[uuid::Uuid]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableDateCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableDateCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::NaiveDate) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::NaiveDate) -> Predicate<T> {
self.gt(val)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableTimeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableTimeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: chrono::NaiveTime) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.ge(val)
}
pub fn before(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.lt(val)
}
pub fn after(&self, val: chrono::NaiveTime) -> Predicate<T> {
self.gt(val)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct JsonCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> JsonCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
pub fn path_text(&self, keys: &[&str]) -> JsonPathText<T> {
JsonPathText::new(self.name, keys)
}
pub fn has_key(&self, key: &str) -> Predicate<T> {
json_has_key_predicate(self.name, key)
}
}
pub struct NullableJsonCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableJsonCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
pub fn path_text(&self, keys: &[&str]) -> JsonPathText<T> {
JsonPathText::new(self.name, keys)
}
pub fn has_key(&self, key: &str) -> Predicate<T> {
json_has_key_predicate(self.name, key)
}
}
pub struct JsonPathText<T> {
column: &'static str,
path: Vec<String>,
_phantom: PhantomData<T>,
}
impl<T> JsonPathText<T> {
fn new(column: &'static str, keys: &[&str]) -> Self {
assert!(
!keys.is_empty(),
"umbral::orm::JsonPathText: path must have at least one segment"
);
Self {
column,
path: keys.iter().map(|s| s.to_string()).collect(),
_phantom: PhantomData,
}
}
fn extract_template_pg(&self, base_placeholder: usize) -> (String, Vec<sea_query::Value>) {
let col = self.column.replace('"', "\"\"");
let n = self.path.len();
let mut sql = format!("\"{col}\"");
for i in 1..n {
sql.push_str(&format!(" -> ${}", base_placeholder + i - 1));
}
sql.push_str(&format!(" ->> ${}", base_placeholder + n - 1));
let values: Vec<sea_query::Value> = self
.path
.iter()
.map(|k| sea_query::Value::String(Some(Box::new(k.clone()))))
.collect();
(sql, values)
}
fn sqlite_json_path(&self) -> String {
let mut s = String::from("$");
for seg in &self.path {
s.push('.');
s.push_str(seg);
}
s
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let (extract_pg, mut pg_values) = self.extract_template_pg(1);
let pg_placeholder = pg_values.len() + 1;
let pg_sql = format!("{extract_pg} = ${pg_placeholder}");
pg_values.push(sea_query::Value::String(Some(Box::new(val.to_string()))));
let pg_cond = Expr::cust_with_values(&pg_sql, pg_values);
let col = self.column.replace('"', "\"\"");
let sqlite_sql = format!("json_extract(\"{col}\", ?) = ?");
let sqlite_values = vec![
sea_query::Value::String(Some(Box::new(self.sqlite_json_path()))),
sea_query::Value::String(Some(Box::new(val.to_string()))),
];
let sqlite_cond = Expr::cust_with_values(&sqlite_sql, sqlite_values);
Predicate::new_with_sqlite(pg_cond, sqlite_cond)
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let (extract_pg, mut pg_values) = self.extract_template_pg(1);
let pg_placeholder = pg_values.len() + 1;
let pg_sql = format!("{extract_pg} <> ${pg_placeholder}");
pg_values.push(sea_query::Value::String(Some(Box::new(val.to_string()))));
let pg_cond = Expr::cust_with_values(&pg_sql, pg_values);
let col = self.column.replace('"', "\"\"");
let sqlite_sql = format!("json_extract(\"{col}\", ?) <> ?");
let sqlite_values = vec![
sea_query::Value::String(Some(Box::new(self.sqlite_json_path()))),
sea_query::Value::String(Some(Box::new(val.to_string()))),
];
let sqlite_cond = Expr::cust_with_values(&sqlite_sql, sqlite_values);
Predicate::new_with_sqlite(pg_cond, sqlite_cond)
}
pub fn is_null(&self) -> Predicate<T> {
let (extract_pg, pg_values) = self.extract_template_pg(1);
let pg_cond = Expr::cust_with_values(format!("{extract_pg} IS NULL"), pg_values);
let col = self.column.replace('"', "\"\"");
let sqlite_sql = format!("json_extract(\"{col}\", ?) IS NULL");
let sqlite_values = vec![sea_query::Value::String(Some(Box::new(
self.sqlite_json_path(),
)))];
let sqlite_cond = Expr::cust_with_values(&sqlite_sql, sqlite_values);
Predicate::new_with_sqlite(pg_cond, sqlite_cond)
}
pub fn is_not_null(&self) -> Predicate<T> {
let (extract_pg, pg_values) = self.extract_template_pg(1);
let pg_cond = Expr::cust_with_values(format!("{extract_pg} IS NOT NULL"), pg_values);
let col = self.column.replace('"', "\"\"");
let sqlite_sql = format!("json_extract(\"{col}\", ?) IS NOT NULL");
let sqlite_values = vec![sea_query::Value::String(Some(Box::new(
self.sqlite_json_path(),
)))];
let sqlite_cond = Expr::cust_with_values(&sqlite_sql, sqlite_values);
Predicate::new_with_sqlite(pg_cond, sqlite_cond)
}
}
fn json_has_key_predicate<T>(col: &'static str, key: &str) -> Predicate<T> {
let col_escaped = col.replace('"', "\"\"");
let key_escaped = key.replace('\'', "''");
let pg_sql = format!("\"{col_escaped}\" ?? '{key_escaped}'");
let pg_cond = Expr::cust(&pg_sql);
let sqlite_sql = format!("json_extract(\"{col_escaped}\", ?) IS NOT NULL");
let sqlite_values = vec![sea_query::Value::String(Some(Box::new(format!("$.{key}"))))];
let sqlite_cond = Expr::cust_with_values(&sqlite_sql, sqlite_values);
Predicate::new_with_sqlite(pg_cond, sqlite_cond)
}
pub struct ArrayCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> ArrayCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
pub fn contains<V: Into<sea_query::Value>>(&self, elem: V) -> Predicate<T> {
array_contains_predicate(self.name, std::iter::once(elem.into()))
}
pub fn contains_all<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_contains_predicate(self.name, elems.into_iter().map(Into::into))
}
pub fn contained_by<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_contained_by_predicate(self.name, elems.into_iter().map(Into::into))
}
pub fn overlaps<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_overlaps_predicate(self.name, elems.into_iter().map(Into::into))
}
}
pub struct NullableArrayCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableArrayCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
pub fn contains<V: Into<sea_query::Value>>(&self, elem: V) -> Predicate<T> {
array_contains_predicate(self.name, std::iter::once(elem.into()))
}
pub fn contains_all<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_contains_predicate(self.name, elems.into_iter().map(Into::into))
}
pub fn contained_by<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_contained_by_predicate(self.name, elems.into_iter().map(Into::into))
}
pub fn overlaps<I, V>(&self, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = V>,
V: Into<sea_query::Value>,
{
array_overlaps_predicate(self.name, elems.into_iter().map(Into::into))
}
}
fn array_op_predicate<T>(
col: &'static str,
op: &str,
values: Vec<sea_query::Value>,
) -> Predicate<T> {
if values.is_empty() {
return Predicate::new(Expr::cust("1 = 1"));
}
let placeholders: Vec<String> = (1..=values.len()).map(|i| format!("${i}")).collect();
let sql = format!(
"\"{}\" {op} ARRAY[{}]",
col.replace('"', "\"\""),
placeholders.join(", ")
);
Predicate::new(Expr::cust_with_values(&sql, values))
}
fn array_contains_predicate<T, I>(col: &'static str, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = sea_query::Value>,
{
array_op_predicate::<T>(col, "@>", elems.into_iter().collect())
}
fn array_contained_by_predicate<T, I>(col: &'static str, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = sea_query::Value>,
{
let values: Vec<sea_query::Value> = elems.into_iter().collect();
if values.is_empty() {
return Predicate::new(Expr::cust("1 = 0"));
}
array_op_predicate::<T>(col, "<@", values)
}
fn array_overlaps_predicate<T, I>(col: &'static str, elems: I) -> Predicate<T>
where
I: IntoIterator<Item = sea_query::Value>,
{
let values: Vec<sea_query::Value> = elems.into_iter().collect();
if values.is_empty() {
return Predicate::new(Expr::cust("1 = 0"));
}
array_op_predicate::<T>(col, "&&", values)
}
pub struct InetCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> InetCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableInetCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableInetCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct CidrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> CidrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableCidrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableCidrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: ipnetwork::IpNetwork) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct MacAddrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> MacAddrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: mac_address::MacAddress) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: mac_address::MacAddress) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct FullTextCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> FullTextCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn matches(&self, query: &str) -> Predicate<T> {
let col = self.name.replace('"', "\"\"");
let sql = format!("\"{col}\" @@ to_tsquery($1)");
let values = vec![sea_query::Value::String(Some(Box::new(query.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn matches_websearch(&self, query: &str) -> Predicate<T> {
let col = self.name.replace('"', "\"\"");
let sql = format!("\"{col}\" @@ websearch_to_tsquery($1)");
let values = vec![sea_query::Value::String(Some(Box::new(query.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableFullTextCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableFullTextCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn matches(&self, query: &str) -> Predicate<T> {
let col = self.name.replace('"', "\"\"");
let sql = format!("\"{col}\" @@ to_tsquery($1)");
let values = vec![sea_query::Value::String(Some(Box::new(query.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn matches_websearch(&self, query: &str) -> Predicate<T> {
let col = self.name.replace('"', "\"\"");
let sql = format!("\"{col}\" @@ websearch_to_tsquery($1)");
let values = vec![sea_query::Value::String(Some(Box::new(query.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableMacAddrCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableMacAddrCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: mac_address::MacAddress) -> Predicate<T> {
let sql = format!("\"{}\" = $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn ne(&self, val: mac_address::MacAddress) -> Predicate<T> {
let sql = format!("\"{}\" <> $1", self.name.replace('"', "\"\""));
Predicate::new(Expr::cust_with_values(&sql, vec![val]))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct XmlCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> XmlCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\"::text = $1", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\"::text <> $1", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableXmlCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableXmlCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\"::text = $1", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\"::text <> $1", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct LtreeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> LtreeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" = $1::ltree", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" <> $1::ltree", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableLtreeCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableLtreeCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" = $1::ltree", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" <> $1::ltree", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct BitCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> BitCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" = $1::bit varying", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" <> $1::bit varying", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableBitCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableBitCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" = $1::bit varying", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn ne(&self, val: &str) -> Predicate<T> {
let sql = format!("\"{}\" <> $1::bit varying", self.name.replace('"', "\"\""));
let values = vec![sea_query::Value::String(Some(Box::new(val.to_string())))];
Predicate::new(Expr::cust_with_values(&sql, values))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct ForeignKeyCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> ForeignKeyCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq<V: Into<sea_query::Value>>(&self, val: V) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val.into()))
}
pub fn ne<V: Into<sea_query::Value>>(&self, val: V) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val.into()))
}
pub fn lt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: i64) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: i64) -> Predicate<T> {
self.ge(val)
}
pub fn in_(&self, vals: &[i64]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn in_subquery(&self, sub: super::Subquery) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).in_subquery(sub.into_statement()))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableForeignKeyCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableForeignKeyCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: i64) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn in_(&self, vals: &[i64]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_in(vals.iter().copied()))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct BytesCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> BytesCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &[u8]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val.to_vec()))
}
pub fn ne(&self, val: &[u8]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val.to_vec()))
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableBytesCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableBytesCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: &[u8]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val.to_vec()))
}
pub fn ne(&self, val: &[u8]) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val.to_vec()))
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct DecimalCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> DecimalCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: rust_decimal::Decimal) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: rust_decimal::Decimal) -> Predicate<T> {
self.ge(val)
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct NullableDecimalCol<T> {
pub(crate) name: &'static str,
_phantom: PhantomData<T>,
}
impl<T> NullableDecimalCol<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_phantom: PhantomData,
}
}
pub fn eq(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).eq(val))
}
pub fn ne(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).ne(val))
}
pub fn lt(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lt(val))
}
pub fn le(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).lte(val))
}
pub fn lte(&self, val: rust_decimal::Decimal) -> Predicate<T> {
self.le(val)
}
pub fn gt(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gt(val))
}
pub fn ge(&self, val: rust_decimal::Decimal) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).gte(val))
}
pub fn gte(&self, val: rust_decimal::Decimal) -> Predicate<T> {
self.ge(val)
}
pub fn is_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_null())
}
pub fn is_not_null(&self) -> Predicate<T> {
Predicate::new(Expr::col(Alias::new(self.name)).is_not_null())
}
pub fn asc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, false)
}
pub fn desc(&self) -> OrderExpr<T> {
OrderExpr::new(self.name, true)
}
}
pub struct ColExpr<T> {
expr: sea_query::SimpleExpr,
expr_sqlite: Option<sea_query::SimpleExpr>,
_phantom: PhantomData<T>,
}
impl<T> ColExpr<T> {
pub(crate) fn new(expr: sea_query::SimpleExpr) -> Self {
Self {
expr,
expr_sqlite: None,
_phantom: PhantomData,
}
}
pub(crate) fn new_with_sqlite(
expr: sea_query::SimpleExpr,
sqlite: sea_query::SimpleExpr,
) -> Self {
Self {
expr,
expr_sqlite: Some(sqlite),
_phantom: PhantomData,
}
}
fn into_predicate<F>(self, op: F) -> Predicate<T>
where
F: Fn(sea_query::SimpleExpr) -> sea_query::SimpleExpr,
{
let cond = op(self.expr);
let cond_sqlite = self.expr_sqlite.map(&op);
match cond_sqlite {
Some(sql) => Predicate::new_with_sqlite(cond, sql),
None => Predicate::new(cond),
}
}
pub fn eq<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.eq(val.clone()))
}
pub fn ne<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.ne(val.clone()))
}
pub fn lt<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.lt(val.clone()))
}
pub fn le<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.lte(val.clone()))
}
pub fn gt<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.gt(val.clone()))
}
pub fn ge<V: Into<sea_query::Value>>(self, val: V) -> Predicate<T> {
let val = val.into();
self.into_predicate(move |e| e.gte(val.clone()))
}
}
pub trait StrColExt<T> {
fn lower(&self) -> ColExpr<T>;
fn upper(&self) -> ColExpr<T>;
fn length(&self) -> ColExpr<T>;
fn trim(&self) -> ColExpr<T>;
fn coalesce<V: Into<sea_query::Value>>(&self, default: V) -> ColExpr<T>;
fn concat<V: Into<sea_query::Value>>(&self, suffix: V) -> ColExpr<T>;
}
fn str_trim_expr(name: &'static str) -> sea_query::SimpleExpr {
Expr::cust(format!("TRIM(\"{}\")", name.replace('"', "\"\"")))
}
fn str_coalesce_expr(name: &'static str, default: sea_query::Value) -> sea_query::SimpleExpr {
let col: sea_query::SimpleExpr = Expr::col(Alias::new(name)).into();
let def: sea_query::SimpleExpr = Expr::val(default).into();
Func::coalesce([col, def]).into()
}
fn str_concat_expr(name: &'static str, suffix: sea_query::Value) -> sea_query::SimpleExpr {
Expr::col(Alias::new(name)).binary(sea_query::BinOper::Custom("||"), Expr::val(suffix))
}
impl<T> StrColExt<T> for StrCol<T> {
fn lower(&self) -> ColExpr<T> {
ColExpr::new(Func::lower(Expr::col(Alias::new(self.name))).into())
}
fn upper(&self) -> ColExpr<T> {
ColExpr::new(Func::upper(Expr::col(Alias::new(self.name))).into())
}
fn length(&self) -> ColExpr<T> {
ColExpr::new(Func::char_length(Expr::col(Alias::new(self.name))).into())
}
fn trim(&self) -> ColExpr<T> {
ColExpr::new(str_trim_expr(self.name))
}
fn coalesce<V: Into<sea_query::Value>>(&self, default: V) -> ColExpr<T> {
ColExpr::new(str_coalesce_expr(self.name, default.into()))
}
fn concat<V: Into<sea_query::Value>>(&self, suffix: V) -> ColExpr<T> {
ColExpr::new(str_concat_expr(self.name, suffix.into()))
}
}
impl<T> StrColExt<T> for NullableStrCol<T> {
fn lower(&self) -> ColExpr<T> {
ColExpr::new(Func::lower(Expr::col(Alias::new(self.name))).into())
}
fn upper(&self) -> ColExpr<T> {
ColExpr::new(Func::upper(Expr::col(Alias::new(self.name))).into())
}
fn length(&self) -> ColExpr<T> {
ColExpr::new(Func::char_length(Expr::col(Alias::new(self.name))).into())
}
fn trim(&self) -> ColExpr<T> {
ColExpr::new(str_trim_expr(self.name))
}
fn coalesce<V: Into<sea_query::Value>>(&self, default: V) -> ColExpr<T> {
ColExpr::new(str_coalesce_expr(self.name, default.into()))
}
fn concat<V: Into<sea_query::Value>>(&self, suffix: V) -> ColExpr<T> {
ColExpr::new(str_concat_expr(self.name, suffix.into()))
}
}
pub trait DateTimeColExt<T> {
fn year(&self) -> ColExpr<T>;
fn month(&self) -> ColExpr<T>;
fn day(&self) -> ColExpr<T>;
fn hour(&self) -> ColExpr<T>;
fn minute(&self) -> ColExpr<T>;
fn second(&self) -> ColExpr<T>;
fn week_day(&self) -> ColExpr<T>;
}
fn date_part_exprs(
col_name: &str,
part_pg: &'static str,
fmt_sqlite: &'static str,
) -> (sea_query::SimpleExpr, sea_query::SimpleExpr) {
let pg = sea_query::SimpleExpr::Custom(format!(
"CAST(EXTRACT({part_pg} FROM \"{col_name}\") AS INTEGER)"
));
let sqlite = sea_query::SimpleExpr::Custom(format!(
"CAST(strftime('{fmt_sqlite}', \"{col_name}\") AS INTEGER)"
));
(pg, sqlite)
}
impl<T> DateTimeColExt<T> for DateTimeCol<T> {
fn year(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "YEAR", "%Y");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn month(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "MONTH", "%m");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn day(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "DAY", "%d");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn hour(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "HOUR", "%H");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn minute(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "MINUTE", "%M");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn second(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "SECOND", "%S");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn week_day(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "DOW", "%w");
ColExpr::new_with_sqlite(pg, sqlite)
}
}
impl<T> DateTimeColExt<T> for NullableDateTimeCol<T> {
fn year(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "YEAR", "%Y");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn month(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "MONTH", "%m");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn day(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "DAY", "%d");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn hour(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "HOUR", "%H");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn minute(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "MINUTE", "%M");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn second(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "SECOND", "%S");
ColExpr::new_with_sqlite(pg, sqlite)
}
fn week_day(&self) -> ColExpr<T> {
let (pg, sqlite) = date_part_exprs(self.name, "DOW", "%w");
ColExpr::new_with_sqlite(pg, sqlite)
}
}