use sea_orm::{
sea_query::{IntoCondition, Order},
ColumnTrait, Condition, Value,
};
use serde::{Deserialize, Serialize};
mod date_range;
pub struct ConditionBuilder {
condition: Condition,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum SortDirection {
#[serde(rename = "desc")]
Desc,
#[serde(rename = "asc")]
Asc,
}
impl SortDirection {
#[must_use]
pub const fn order(&self) -> Order {
match self {
Self::Desc => Order::Desc,
Self::Asc => Order::Asc,
}
}
}
#[must_use]
pub fn condition() -> ConditionBuilder {
ConditionBuilder {
condition: Condition::all(),
}
}
#[must_use]
pub const fn with(condition: Condition) -> ConditionBuilder {
ConditionBuilder { condition }
}
impl ConditionBuilder {
#[must_use]
pub fn eq<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.eq(value)))
}
#[must_use]
pub fn ne<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.ne(value)))
}
#[must_use]
pub fn gt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.gt(value)))
}
#[must_use]
pub fn gte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.gte(value)))
}
#[must_use]
pub fn lt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.lt(value)))
}
#[must_use]
pub fn lte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
with(self.condition.add(col.lte(value)))
}
#[must_use]
pub fn between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V, b: V) -> Self {
with(self.condition.add(col.between(a, b)))
}
#[must_use]
pub fn not_between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V, b: V) -> Self {
with(self.condition.add(col.not_between(a, b)))
}
#[must_use]
pub fn like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
with(self.condition.add(col.like(a)))
}
#[must_use]
pub fn not_like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
with(self.condition.add(col.not_like(a)))
}
#[must_use]
pub fn starts_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
with(self.condition.add(col.starts_with(a)))
}
#[must_use]
pub fn ends_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
with(self.condition.add(col.ends_with(a)))
}
#[must_use]
pub fn contains<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
with(self.condition.add(col.contains(a)))
}
#[must_use]
#[allow(clippy::wrong_self_convention)]
pub fn is_null<T: ColumnTrait>(self, col: T) -> Self {
with(self.condition.add(col.is_null()))
}
#[must_use]
#[allow(clippy::wrong_self_convention)]
pub fn is_not_null<T: ColumnTrait>(self, col: T) -> Self {
with(self.condition.add(col.is_not_null()))
}
#[must_use]
#[allow(clippy::wrong_self_convention)]
pub fn is_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
self,
col: T,
values: I,
) -> Self {
with(self.condition.add(col.is_in(values)))
}
#[must_use]
#[allow(clippy::wrong_self_convention)]
pub fn is_not_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
self,
col: T,
values: I,
) -> Self {
with(self.condition.add(col.is_not_in(values)))
}
#[must_use]
pub fn date_range<T: ColumnTrait>(self, col: T) -> date_range::DateRangeBuilder<T> {
date_range::DateRangeBuilder::new(self, col)
}
#[must_use]
pub fn build(&self) -> Condition {
self.condition.clone().into_condition()
}
}
#[cfg(test)]
mod tests {
use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
use super::*;
use crate::tests_cfg::db::*;
#[test]
fn condition_eq() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().eq(test_db::Column::Id, 1).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" = 1"
);
}
#[test]
fn condition_ne() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().ne(test_db::Column::Name, "loco").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" <> 'loco'"
);
}
#[test]
fn condition_gt() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().gt(test_db::Column::Id, 1).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" > 1"
);
}
#[test]
fn condition_gte() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().gte(test_db::Column::Id, 1).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" >= 1"
);
}
#[test]
fn condition_lt() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().lt(test_db::Column::Id, 1).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" < 1"
);
}
#[test]
fn condition_lte() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().lte(test_db::Column::Id, 1).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" <= 1"
);
}
#[test]
fn condition_between() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().between(test_db::Column::Id, 1, 2).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" BETWEEN 1 AND 2"
);
}
#[test]
fn condition_not_between() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().not_between(test_db::Column::Id, 1, 2).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT BETWEEN 1 AND 2"
);
}
#[test]
fn condition_like() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().like(test_db::Column::Name, "%lo").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
);
}
#[test]
fn condition_not_like() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().not_like(test_db::Column::Name, "%lo%").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" NOT LIKE '%lo%'"
);
}
#[test]
fn condition_starts_with() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().starts_with(test_db::Column::Name, "lo").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE 'lo%'"
);
}
#[test]
fn condition_ends_with() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().ends_with(test_db::Column::Name, "lo").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
);
}
#[test]
fn condition_contains() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().contains(test_db::Column::Name, "lo").build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo%'"
);
}
#[test]
fn condition_is_null() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().is_null(test_db::Column::Name).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NULL"
);
}
#[test]
fn condition_is_not_null() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().is_not_null(test_db::Column::Name).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NOT NULL"
);
}
#[test]
fn condition_is_in() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().is_in(test_db::Column::Id, [1]).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" IN (1)"
);
}
#[test]
fn condition_is_not_in() {
let query_str = test_db::Entity::find()
.select_only()
.column(test_db::Column::Id)
.filter(condition().is_not_in(test_db::Column::Id, [1]).build())
.build(sea_orm::DatabaseBackend::Postgres)
.to_string();
assert_eq!(
query_str,
"SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT IN (1)"
);
}
}