use crate::core::condition::SqlValue;
use crate::orm::model_query::ModelQuery;
use crate::orm::postgres::model::PgModel;
#[derive(Debug, Clone)]
pub struct FilterBuilder<M> {
conditions: Vec<FilterCondition>,
_marker: std::marker::PhantomData<M>,
}
impl<M: PgModel + Sync> Default for FilterBuilder<M> {
fn default() -> Self {
Self {
conditions: Vec::new(),
_marker: std::marker::PhantomData,
}
}
}
#[derive(Debug, Clone)]
enum FilterCondition {
Eq(String, SqlValue),
Ne(String, SqlValue),
Gt(String, SqlValue),
Gte(String, SqlValue),
Lt(String, SqlValue),
Lte(String, SqlValue),
Like(String, String),
ILike(String, String),
IsNull(String),
IsNotNull(String),
In(String, Vec<SqlValue>),
NotIn(String, Vec<SqlValue>),
}
impl<M: PgModel + Sync> FilterBuilder<M> {
pub fn new() -> Self {
Self::default()
}
pub fn eq(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Eq(col.into(), val.into()));
self
}
pub fn ne(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Ne(col.into(), val.into()));
self
}
pub fn gt(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Gt(col.into(), val.into()));
self
}
pub fn gte(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Gte(col.into(), val.into()));
self
}
pub fn lt(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Lt(col.into(), val.into()));
self
}
pub fn lte(mut self, col: impl Into<String>, val: impl Into<SqlValue>) -> Self {
self.conditions
.push(FilterCondition::Lte(col.into(), val.into()));
self
}
pub fn like(mut self, col: impl Into<String>, pattern: impl Into<String>) -> Self {
self.conditions
.push(FilterCondition::Like(col.into(), pattern.into()));
self
}
pub fn ilike(mut self, col: impl Into<String>, pattern: impl Into<String>) -> Self {
self.conditions
.push(FilterCondition::ILike(col.into(), pattern.into()));
self
}
pub fn is_null(mut self, col: impl Into<String>) -> Self {
self.conditions.push(FilterCondition::IsNull(col.into()));
self
}
pub fn is_not_null(mut self, col: impl Into<String>) -> Self {
self.conditions.push(FilterCondition::IsNotNull(col.into()));
self
}
pub fn in_(
mut self,
col: impl Into<String>,
vals: impl IntoIterator<Item = impl Into<SqlValue>>,
) -> Self {
self.conditions.push(FilterCondition::In(
col.into(),
vals.into_iter().map(Into::into).collect(),
));
self
}
pub fn not_in(
mut self,
col: impl Into<String>,
vals: impl IntoIterator<Item = impl Into<SqlValue>>,
) -> Self {
self.conditions.push(FilterCondition::NotIn(
col.into(),
vals.into_iter().map(Into::into).collect(),
));
self
}
pub fn apply(&self, mut query: ModelQuery<M>) -> ModelQuery<M> {
for cond in &self.conditions {
query = match cond {
FilterCondition::Eq(c, v) => query.and_where(c, v.clone()),
FilterCondition::Ne(c, v) => query.and_where_op(c, "!=", v.clone()),
FilterCondition::Gt(c, v) => query.and_where_op(c, ">", v.clone()),
FilterCondition::Gte(c, v) => query.and_where_op(c, ">=", v.clone()),
FilterCondition::Lt(c, v) => query.and_where_op(c, "<", v.clone()),
FilterCondition::Lte(c, v) => query.and_where_op(c, "<=", v.clone()),
FilterCondition::Like(c, p) => query.and_where_like(c, p),
FilterCondition::ILike(c, p) => query.and_where_ilike(c, p),
FilterCondition::IsNull(c) => query.and_where_null(c),
FilterCondition::IsNotNull(c) => query.and_where_not_null(c),
FilterCondition::In(c, vs) => query.and_where_in(c, vs.clone()),
FilterCondition::NotIn(c, vs) => query.and_where_not_in(c, vs.clone()),
};
}
query
}
}