Select filters
This commit is contained in:
parent
3f5b0080da
commit
8e4271da79
@ -1,6 +1,6 @@
|
||||
use super::{ColumnTrait, Identity, ModelTrait, RelationTrait};
|
||||
use crate::Select;
|
||||
use sea_query::Iden;
|
||||
use sea_query::{Expr, Iden, Value};
|
||||
use std::fmt::Debug;
|
||||
pub use strum::IntoEnumIterator as Iterable;
|
||||
|
||||
@ -20,4 +20,20 @@ pub trait EntityTrait: Iden + Default + Debug {
|
||||
fn find<'s>() -> Select<'s, Self> {
|
||||
Select::new(Self::default())
|
||||
}
|
||||
|
||||
fn find_one<'s>() -> Select<'s, Self> {
|
||||
let mut select = Self::find();
|
||||
select.query().limit(1);
|
||||
select
|
||||
}
|
||||
|
||||
fn find_one_by<'s, V>(v: V) -> Select<'s, Self>
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
let select = Self::find_one();
|
||||
let select =
|
||||
select.filter(Expr::tbl(Self::default(), Self::primary_key().into_iden()).eq(v));
|
||||
select
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,69 @@
|
||||
use crate::EntityTrait;
|
||||
pub use sea_query::ColumnType;
|
||||
use sea_query::Iden;
|
||||
use sea_query::{Expr, Iden, SimpleExpr, Value};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait ColumnTrait: Iden {
|
||||
fn col_type(&self) -> ColumnType;
|
||||
macro_rules! bind_oper {
|
||||
( $op: ident ) => {
|
||||
fn $op<V>(&'static self, v: V) -> SimpleExpr
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
Expr::tbl(self.entity_iden(), *self).$op(v)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub trait ColumnTrait: Iden + Copy {
|
||||
type Entity: EntityTrait;
|
||||
|
||||
fn col_type(&self) -> ColumnType;
|
||||
|
||||
fn entity_iden(&'static self) -> Rc<dyn Iden> {
|
||||
Rc::new(Self::Entity::default()) as Rc<dyn Iden>
|
||||
}
|
||||
|
||||
bind_oper!(eq);
|
||||
bind_oper!(ne);
|
||||
bind_oper!(gt);
|
||||
bind_oper!(gte);
|
||||
bind_oper!(lt);
|
||||
bind_oper!(lte);
|
||||
|
||||
fn between<V>(&'static self, a: V, b: V) -> SimpleExpr
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
Expr::tbl(self.entity_iden(), *self).between(a, b)
|
||||
}
|
||||
|
||||
fn not_between<V>(&'static self, a: V, b: V) -> SimpleExpr
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
Expr::tbl(self.entity_iden(), *self).not_between(a, b)
|
||||
}
|
||||
|
||||
fn like(&'static self, s: &str) -> SimpleExpr {
|
||||
Expr::tbl(self.entity_iden(), *self).like(s)
|
||||
}
|
||||
|
||||
fn not_like(&'static self, s: &str) -> SimpleExpr {
|
||||
Expr::tbl(self.entity_iden(), *self).not_like(s)
|
||||
}
|
||||
|
||||
fn starts_with(&'static self, s: &str) -> SimpleExpr {
|
||||
let pattern = format!("{}%", s);
|
||||
Expr::tbl(self.entity_iden(), *self).like(&pattern)
|
||||
}
|
||||
|
||||
fn ends_with(&'static self, s: &str) -> SimpleExpr {
|
||||
let pattern = format!("%{}", s);
|
||||
Expr::tbl(self.entity_iden(), *self).like(&pattern)
|
||||
}
|
||||
|
||||
fn contains(&'static self, s: &str) -> SimpleExpr {
|
||||
let pattern = format!("%{}%", s);
|
||||
Expr::tbl(self.entity_iden(), *self).like(&pattern)
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,14 @@ pub trait IntoIdentity {
|
||||
fn into_identity(self) -> Identity;
|
||||
}
|
||||
|
||||
impl Identity {
|
||||
pub fn into_iden(self) -> Rc<dyn Iden> {
|
||||
match self {
|
||||
Self::Unary(iden) => iden,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIdentity for T
|
||||
where
|
||||
T: IntoIden,
|
||||
|
@ -12,5 +12,6 @@ pub use driver::*;
|
||||
pub use entity::*;
|
||||
pub use query::*;
|
||||
|
||||
pub use sea_query;
|
||||
pub use sea_query::Iden;
|
||||
pub use strum::EnumIter;
|
@ -2,7 +2,7 @@ use crate::{EntityTrait, Identity, Iterable, RelationDef, Statement};
|
||||
use core::fmt::Debug;
|
||||
use core::marker::PhantomData;
|
||||
pub use sea_query::JoinType;
|
||||
use sea_query::{Expr, Iden, IntoIden, QueryBuilder, SelectStatement};
|
||||
use sea_query::{Expr, Iden, IntoIden, QueryBuilder, SelectStatement, SimpleExpr};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -54,6 +54,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn filter(mut self, expr: SimpleExpr) -> Self {
|
||||
self.select.and_where(expr);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn left_join(self, relation: RelationDef) -> Self {
|
||||
self.prepare_join(JoinType::LeftJoin, relation)
|
||||
}
|
||||
@ -89,16 +94,77 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests_cfg::cake;
|
||||
use crate::EntityTrait;
|
||||
use sea_query::MySqlQueryBuilder;
|
||||
use crate::{ColumnTrait, EntityTrait};
|
||||
use sea_query::MysqlQueryBuilder;
|
||||
|
||||
#[test]
|
||||
fn test_1() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.build(MySqlQueryBuilder::default())
|
||||
.to_string(),
|
||||
cake::Entity::find().build(MysqlQueryBuilder).to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(cake::Column::Id.eq(5))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 5"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_3() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(cake::Column::Name.like("cheese"))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese'"
|
||||
);
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(cake::Column::Name.starts_with("cheese"))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese%'"
|
||||
);
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(cake::Column::Name.ends_with("cheese"))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese'"
|
||||
);
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(cake::Column::Name.contains("cheese"))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese%'"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_4() {
|
||||
assert_eq!(
|
||||
cake::Entity::find_one()
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` LIMIT 1"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_5() {
|
||||
assert_eq!(
|
||||
cake::Entity::find_one_by(11)
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 11 LIMIT 1"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
ColumnTrait, ColumnType, EntityTrait, Identity, IntoIdentity, ModelTrait, QueryResult, RelationDef,
|
||||
RelationTrait, TypeErr, EnumIter, Iden
|
||||
ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait,
|
||||
QueryResult, RelationDef, RelationTrait, TypeErr,
|
||||
};
|
||||
|
||||
#[derive(Iden, Default, Debug)]
|
||||
#[derive(Default, Debug, Iden)]
|
||||
#[iden = "cake"]
|
||||
pub struct Entity;
|
||||
|
||||
@ -13,13 +13,13 @@ pub struct Model {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Iden, EnumIter)]
|
||||
#[derive(Copy, Clone, Iden, EnumIter)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
}
|
||||
|
||||
#[derive(EnumIter)]
|
||||
#[derive(Copy, Clone, EnumIter)]
|
||||
pub enum Relation {}
|
||||
|
||||
impl EntityTrait for Entity {
|
||||
@ -44,6 +44,8 @@ impl ModelTrait for Model {
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type Entity = Entity;
|
||||
|
||||
fn col_type(&self) -> ColumnType {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer(None),
|
||||
|
Loading…
x
Reference in New Issue
Block a user