diff --git a/examples/sqlx-mysql/src/main.rs b/examples/sqlx-mysql/src/main.rs index 2bb1c652..a9682663 100644 --- a/examples/sqlx-mysql/src/main.rs +++ b/examples/sqlx-mysql/src/main.rs @@ -1,4 +1,4 @@ -use sea_orm::{ColumnTrait, Database, EntityTrait, QueryErr, SelectQuery}; +use sea_orm::{ColumnTrait, Database, EntityTrait, QueryErr, QueryHelper}; mod example_cake; mod example_fruit; diff --git a/src/connector/select.rs b/src/connector/select.rs index 1c1ba533..7f2745bb 100644 --- a/src/connector/select.rs +++ b/src/connector/select.rs @@ -3,7 +3,7 @@ use sea_query::{QueryBuilder, SelectStatement}; use std::marker::PhantomData; #[derive(Clone, Debug)] -pub struct SingleSelect +pub struct SelectModel where M: FromQueryResult, { @@ -12,7 +12,7 @@ where } #[derive(Clone, Debug)] -pub struct DoubleSelect +pub struct SelectTwoModel where M: FromQueryResult, N: FromQueryResult, @@ -25,11 +25,11 @@ impl Select where E: EntityTrait, { - pub fn into_model(self) -> SingleSelect + pub fn into_model(self) -> SelectModel where M: FromQueryResult, { - SingleSelect { + SelectModel { query: self.query, model: PhantomData, } @@ -44,7 +44,7 @@ where } } -impl SingleSelect +impl SelectModel where M: FromQueryResult, { diff --git a/src/entity/base.rs b/src/entity/base.rs index 43b2beb9..3d690f57 100644 --- a/src/entity/base.rs +++ b/src/entity/base.rs @@ -1,6 +1,6 @@ use crate::{ - ColumnTrait, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, RelationBuilder, RelationTrait, - RelationType, Select, SelectQuery, + ColumnTrait, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryHelper, RelationBuilder, + RelationTrait, RelationType, Select, }; use sea_query::{Iden, IntoIden, Value}; use std::fmt::Debug; diff --git a/src/entity/column.rs b/src/entity/column.rs index a4702537..b1e8a679 100644 --- a/src/entity/column.rs +++ b/src/entity/column.rs @@ -57,7 +57,7 @@ pub trait ColumnTrait: IdenStatic { bind_oper!(lte); /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -75,7 +75,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -93,7 +93,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -108,7 +108,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -123,7 +123,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -139,7 +139,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() @@ -155,7 +155,7 @@ pub trait ColumnTrait: IdenStatic { } /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// /// assert_eq!( /// cake::Entity::find() diff --git a/src/query/helper.rs b/src/query/helper.rs new file mode 100644 index 00000000..b1ba60e3 --- /dev/null +++ b/src/query/helper.rs @@ -0,0 +1,140 @@ +use crate::{ColumnTrait, IntoSimpleExpr}; + +pub use sea_query::JoinType; +use sea_query::{Alias, Order, SelectExpr, SelectStatement, SimpleExpr}; +use std::rc::Rc; + +pub trait QueryHelper: Sized { + fn query(&mut self) -> &mut SelectStatement; + + fn select_only(mut self) -> Self { + self.query().clear_selects(); + self + } + + /// Add a select column + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::PostgresQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .select_only() + /// .column(cake::Column::Name) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"SELECT "cake"."name" FROM "cake""# + /// ); + /// ``` + fn column(mut self, col: C) -> Self + where + C: ColumnTrait, + { + self.query().expr(col.into_simple_expr()); + self + } + + /// Add a select column with alias + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::PostgresQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .select_only() + /// .column_as(cake::Column::Id.count(), "count") + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"SELECT COUNT("cake"."id") AS "count" FROM "cake""# + /// ); + /// ``` + fn column_as(mut self, col: C, alias: &str) -> Self + where + C: IntoSimpleExpr, + { + self.query().expr(SelectExpr { + expr: col.into_simple_expr(), + alias: Some(Rc::new(Alias::new(alias))), + }); + self + } + + /// Add an AND WHERE expression + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// 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" + /// ); + /// ``` + fn filter(mut self, expr: SimpleExpr) -> Self { + self.query().and_where(expr); + self + } + + /// Add a group by column + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, QueryHelper, tests_cfg::cake, sea_query::PostgresQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .select_only() + /// .column(cake::Column::Name) + /// .group_by(cake::Column::Name) + /// .build(PostgresQueryBuilder) + /// .to_string(), + /// r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""# + /// ); + /// ``` + fn group_by(mut self, col: C) -> Self + where + C: IntoSimpleExpr, + { + self.query().add_group_by(vec![col.into_simple_expr()]); + self + } + + /// Add an order_by expression (ascending) + /// ``` + /// use sea_orm::{EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .order_by(cake::Column::Id) + /// .build(MysqlQueryBuilder) + /// .to_string(), + /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC" + /// ); + /// ``` + fn order_by(mut self, col: C) -> Self + where + C: IntoSimpleExpr, + { + self.query() + .order_by_expr(col.into_simple_expr(), Order::Asc); + self + } + + /// Add an order_by expression (descending) + /// ``` + /// use sea_orm::{EntityTrait, QueryHelper, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .order_by_desc(cake::Column::Id) + /// .build(MysqlQueryBuilder) + /// .to_string(), + /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` DESC" + /// ); + /// ``` + fn order_by_desc(mut self, col: C) -> Self + where + C: IntoSimpleExpr, + { + self.query() + .order_by_expr(col.into_simple_expr(), Order::Desc); + self + } +} diff --git a/src/query/join.rs b/src/query/join.rs new file mode 100644 index 00000000..33cefb24 --- /dev/null +++ b/src/query/join.rs @@ -0,0 +1,197 @@ +use crate::{ + ColumnTrait, EntityTrait, Identity, Iterable, ModelTrait, PrimaryKeyOfModel, QueryHelper, + Related, RelationDef, Select, +}; + +pub use sea_query::JoinType; +use sea_query::{Expr, IntoIden}; +use std::rc::Rc; + +impl Select +where + E: EntityTrait, +{ + pub fn belongs_to(self, model: &R::Model) -> Self + where + R: EntityTrait + Related, + R::PrimaryKey: PrimaryKeyOfModel, + { + if let Some(key) = R::PrimaryKey::iter().next() { + // TODO: supporting composite primary key + let col = key.into_column(); + self.filter(col.eq(model.get(col))) + } else { + panic!("undefined primary key"); + } + } + + /// Join via [`RelationDef`]. + pub fn join(mut self, join: JoinType, rel: RelationDef) -> Self { + let own_tbl = E::default().into_iden(); + let to_tbl = rel.to_tbl.clone(); + let owner_keys = rel.from_col; + let foreign_keys = rel.to_col; + let condition = match (owner_keys, foreign_keys) { + (Identity::Unary(o1), Identity::Unary(f1)) => { + Expr::tbl(Rc::clone(&own_tbl), o1).equals(Rc::clone(&to_tbl), f1) + } // _ => panic!("Owner key and foreign key mismatch"), + }; + self.query.join(join, Rc::clone(&to_tbl), condition); + self + } + + /// Join via [`RelationDef`] but in reverse direction. + /// Assume when there exist a relation A -> B. + /// You can reverse join B <- A. + pub fn join_rev(mut self, join: JoinType, rel: RelationDef) -> Self { + let from_tbl = rel.from_tbl.clone(); + let to_tbl = rel.to_tbl.clone(); + let owner_keys = rel.from_col; + let foreign_keys = rel.to_col; + let condition = match (owner_keys, foreign_keys) { + (Identity::Unary(o1), Identity::Unary(f1)) => { + Expr::tbl(Rc::clone(&from_tbl), o1).equals(Rc::clone(&to_tbl), f1) + } // _ => panic!("Owner key and foreign key mismatch"), + }; + self.query.join(join, Rc::clone(&from_tbl), condition); + self + } + + /// Left Join with a Related Entity. + pub fn left_join(self, _: R) -> Self + where + R: EntityTrait, + E: Related, + { + self.join(JoinType::LeftJoin, E::to()) + } + + /// Right Join with a Related Entity. + pub fn right_join(self, _: R) -> Self + where + R: EntityTrait, + E: Related, + { + self.join(JoinType::RightJoin, E::to()) + } + + /// Inner Join with a Related Entity. + pub fn inner_join(self, _: R) -> Self + where + R: EntityTrait, + E: Related, + { + self.join(JoinType::InnerJoin, E::to()) + } + + /// Join with an Entity Related to me. + pub fn reverse_join(self, _: R) -> Self + where + R: EntityTrait + Related, + { + self.join_rev(JoinType::InnerJoin, R::to()) + } +} + +#[cfg(test)] +mod tests { + use crate::tests_cfg::{cake, fruit}; + use crate::{ColumnTrait, EntityTrait, QueryHelper}; + use sea_query::MysqlQueryBuilder; + + #[test] + fn join_1() { + assert_eq!( + cake::Entity::find() + .left_join(fruit::Entity) + .build(MysqlQueryBuilder) + .to_string(), + [ + "SELECT `cake`.`id`, `cake`.`name` FROM `cake`", + "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`", + ] + .join(" ") + ); + } + + #[test] + fn join_2() { + assert_eq!( + cake::Entity::find() + .inner_join(fruit::Entity) + .filter(fruit::Column::Name.contains("cherry")) + .build(MysqlQueryBuilder) + .to_string(), + [ + "SELECT `cake`.`id`, `cake`.`name` FROM `cake`", + "INNER JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`", + "WHERE `fruit`.`name` LIKE \'%cherry%\'" + ] + .join(" ") + ); + } + + #[test] + fn join_3() { + assert_eq!( + fruit::Entity::find() + .reverse_join(cake::Entity) + .build(MysqlQueryBuilder) + .to_string(), + [ + "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", + "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", + ] + .join(" ") + ); + } + + #[test] + fn join_4() { + use crate::{Related, Select}; + + let find_fruit: Select = cake::Entity::find_related(); + assert_eq!( + find_fruit + .filter(cake::Column::Id.eq(11)) + .build(MysqlQueryBuilder) + .to_string(), + [ + "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", + "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", + "WHERE `cake`.`id` = 11", + ] + .join(" ") + ); + } + + #[test] + fn join_5() { + let cake_model = cake::Model { + id: 12, + name: "".to_owned(), + }; + + assert_eq!( + cake_model.find_fruit().build(MysqlQueryBuilder).to_string(), + [ + "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", + "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", + "WHERE `cake`.`id` = 12", + ] + .join(" ") + ); + } + + #[test] + fn alias_1() { + assert_eq!( + cake::Entity::find() + .column_as(cake::Column::Id, "B") + .apply_alias("A_") + .build(MysqlQueryBuilder) + .to_string(), + "SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`, `cake`.`id` AS `A_B` FROM `cake`", + ); + } +} diff --git a/src/query/mod.rs b/src/query/mod.rs index 33091d5a..f48b7dca 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -1,5 +1,9 @@ +mod helper; +mod join; mod result; mod select; +pub use helper::*; +pub use join::*; pub use result::*; pub use select::*; diff --git a/src/query/select.rs b/src/query/select.rs index bdc101ae..1a8e1747 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -1,13 +1,9 @@ -use crate::{ - ColumnTrait, EntityTrait, Identity, Iterable, ModelTrait, PrimaryKeyOfModel, Related, - RelationDef, Statement, -}; +use crate::{ColumnTrait, EntityTrait, Iterable, QueryHelper, Statement}; use core::fmt::Debug; use core::marker::PhantomData; pub use sea_query::JoinType; use sea_query::{ - Alias, ColumnRef, Expr, Iden, IntoColumnRef, IntoIden, Order, QueryBuilder, SelectExpr, - SelectStatement, SimpleExpr, + Alias, ColumnRef, Iden, IntoColumnRef, IntoIden, QueryBuilder, SelectStatement, SimpleExpr, }; use std::rc::Rc; @@ -20,10 +16,39 @@ where pub(crate) entity: PhantomData, } +#[derive(Clone, Debug)] +pub struct SelectTwo +where + E: EntityTrait, + F: EntityTrait, +{ + pub(crate) query: SelectStatement, + pub(crate) entity: PhantomData<(E, F)>, +} + pub trait IntoSimpleExpr { fn into_simple_expr(self) -> SimpleExpr; } +impl QueryHelper for Select +where + E: EntityTrait, +{ + fn query(&mut self) -> &mut SelectStatement { + &mut self.query + } +} + +impl QueryHelper for SelectTwo +where + E: EntityTrait, + F: EntityTrait, +{ + fn query(&mut self) -> &mut SelectStatement { + &mut self.query + } +} + impl IntoSimpleExpr for C where C: ColumnTrait, @@ -67,7 +92,7 @@ where self } - fn apply_alias(mut self, pre: &str) -> Self { + pub(crate) fn apply_alias(mut self, pre: &str) -> Self { self.query().exprs_mut_for_each(|sel| { match &sel.alias { Some(alias) => { @@ -90,87 +115,6 @@ where self } - pub fn belongs_to(self, model: &R::Model) -> Self - where - R: EntityTrait + Related, - R::PrimaryKey: PrimaryKeyOfModel, - { - if let Some(key) = R::PrimaryKey::iter().next() { - // TODO: supporting composite primary key - let col = key.into_column(); - self.filter(col.eq(model.get(col))) - } else { - panic!("undefined primary key"); - } - } - - /// Join via [`RelationDef`]. - pub fn join(mut self, join: JoinType, rel: RelationDef) -> Self { - let own_tbl = E::default().into_iden(); - let to_tbl = rel.to_tbl.clone(); - let owner_keys = rel.from_col; - let foreign_keys = rel.to_col; - let condition = match (owner_keys, foreign_keys) { - (Identity::Unary(o1), Identity::Unary(f1)) => { - Expr::tbl(Rc::clone(&own_tbl), o1).equals(Rc::clone(&to_tbl), f1) - } // _ => panic!("Owner key and foreign key mismatch"), - }; - self.query.join(join, Rc::clone(&to_tbl), condition); - self - } - - /// Join via [`RelationDef`] but in reverse direction. - /// Assume when there exist a relation A -> B. - /// You can reverse join B <- A. - pub fn join_rev(mut self, join: JoinType, rel: RelationDef) -> Self { - let from_tbl = rel.from_tbl.clone(); - let to_tbl = rel.to_tbl.clone(); - let owner_keys = rel.from_col; - let foreign_keys = rel.to_col; - let condition = match (owner_keys, foreign_keys) { - (Identity::Unary(o1), Identity::Unary(f1)) => { - Expr::tbl(Rc::clone(&from_tbl), o1).equals(Rc::clone(&to_tbl), f1) - } // _ => panic!("Owner key and foreign key mismatch"), - }; - self.query.join(join, Rc::clone(&from_tbl), condition); - self - } - - /// Left Join with a Related Entity. - pub fn left_join(self, _: R) -> Self - where - R: EntityTrait, - E: Related, - { - self.join(JoinType::LeftJoin, E::to()) - } - - /// Right Join with a Related Entity. - pub fn right_join(self, _: R) -> Self - where - R: EntityTrait, - E: Related, - { - self.join(JoinType::RightJoin, E::to()) - } - - /// Inner Join with a Related Entity. - pub fn inner_join(self, _: R) -> Self - where - R: EntityTrait, - E: Related, - { - self.join(JoinType::InnerJoin, E::to()) - } - - /// Join with an Entity Related to me. - pub fn reverse_join(self, _: R) -> Self - where - R: EntityTrait + Related, - { - self.join_rev(JoinType::InnerJoin, R::to()) - } - /// Get a mutable ref to the query builder pub fn query(&mut self) -> &mut SelectStatement { &mut self.query @@ -195,240 +139,12 @@ where } } -pub trait SelectQuery: Sized { - fn query(&mut self) -> &mut SelectStatement; - - fn select_only(mut self) -> Self { - self.query().clear_selects(); - self - } - - /// Add a select column - /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::PostgresQueryBuilder}; - /// - /// assert_eq!( - /// cake::Entity::find() - /// .select_only() - /// .column(cake::Column::Name) - /// .build(PostgresQueryBuilder) - /// .to_string(), - /// r#"SELECT "cake"."name" FROM "cake""# - /// ); - /// ``` - fn column(mut self, col: C) -> Self - where - C: ColumnTrait, - { - self.query().expr(col.into_simple_expr()); - self - } - - /// Add a select column with alias - /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::PostgresQueryBuilder}; - /// - /// assert_eq!( - /// cake::Entity::find() - /// .select_only() - /// .column_as(cake::Column::Id.count(), "count") - /// .build(PostgresQueryBuilder) - /// .to_string(), - /// r#"SELECT COUNT("cake"."id") AS "count" FROM "cake""# - /// ); - /// ``` - fn column_as(mut self, col: C, alias: &str) -> Self - where - C: IntoSimpleExpr, - { - self.query().expr(SelectExpr { - expr: col.into_simple_expr(), - alias: Some(Rc::new(Alias::new(alias))), - }); - self - } - - /// Add an AND WHERE expression - /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; - /// - /// 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" - /// ); - /// ``` - fn filter(mut self, expr: SimpleExpr) -> Self { - self.query().and_where(expr); - self - } - - /// Add a group by column - /// ``` - /// use sea_orm::{ColumnTrait, EntityTrait, SelectQuery, tests_cfg::cake, sea_query::PostgresQueryBuilder}; - /// - /// assert_eq!( - /// cake::Entity::find() - /// .select_only() - /// .column(cake::Column::Name) - /// .group_by(cake::Column::Name) - /// .build(PostgresQueryBuilder) - /// .to_string(), - /// r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""# - /// ); - /// ``` - fn group_by(mut self, col: C) -> Self - where - C: IntoSimpleExpr, - { - self.query().add_group_by(vec![col.into_simple_expr()]); - self - } - - /// Add an order_by expression (ascending) - /// ``` - /// use sea_orm::{EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; - /// - /// assert_eq!( - /// cake::Entity::find() - /// .order_by(cake::Column::Id) - /// .build(MysqlQueryBuilder) - /// .to_string(), - /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC" - /// ); - /// ``` - fn order_by(mut self, col: C) -> Self - where - C: IntoSimpleExpr, - { - self.query() - .order_by_expr(col.into_simple_expr(), Order::Asc); - self - } - - /// Add an order_by expression (descending) - /// ``` - /// use sea_orm::{EntityTrait, SelectQuery, tests_cfg::cake, sea_query::MysqlQueryBuilder}; - /// - /// assert_eq!( - /// cake::Entity::find() - /// .order_by_desc(cake::Column::Id) - /// .build(MysqlQueryBuilder) - /// .to_string(), - /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` DESC" - /// ); - /// ``` - fn order_by_desc(mut self, col: C) -> Self - where - C: IntoSimpleExpr, - { - self.query() - .order_by_expr(col.into_simple_expr(), Order::Desc); - self - } -} - -impl SelectQuery for Select -where - E: EntityTrait, -{ - fn query(&mut self) -> &mut SelectStatement { - &mut self.query - } -} - #[cfg(test)] mod tests { - use crate::tests_cfg::{cake, fruit}; - use crate::{ColumnTrait, EntityTrait, SelectQuery}; + use crate::tests_cfg::cake; + use crate::{EntityTrait, QueryHelper}; use sea_query::MysqlQueryBuilder; - #[test] - fn join_1() { - assert_eq!( - cake::Entity::find() - .left_join(fruit::Entity) - .build(MysqlQueryBuilder) - .to_string(), - [ - "SELECT `cake`.`id`, `cake`.`name` FROM `cake`", - "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`", - ] - .join(" ") - ); - } - - #[test] - fn join_2() { - assert_eq!( - cake::Entity::find() - .inner_join(fruit::Entity) - .filter(fruit::Column::Name.contains("cherry")) - .build(MysqlQueryBuilder) - .to_string(), - [ - "SELECT `cake`.`id`, `cake`.`name` FROM `cake`", - "INNER JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`", - "WHERE `fruit`.`name` LIKE \'%cherry%\'" - ] - .join(" ") - ); - } - - #[test] - fn join_3() { - assert_eq!( - fruit::Entity::find() - .reverse_join(cake::Entity) - .build(MysqlQueryBuilder) - .to_string(), - [ - "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", - "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", - ] - .join(" ") - ); - } - - #[test] - fn join_4() { - use crate::{Related, Select}; - - let find_fruit: Select = cake::Entity::find_related(); - assert_eq!( - find_fruit - .filter(cake::Column::Id.eq(11)) - .build(MysqlQueryBuilder) - .to_string(), - [ - "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", - "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", - "WHERE `cake`.`id` = 11", - ] - .join(" ") - ); - } - - #[test] - fn join_5() { - let cake_model = cake::Model { - id: 12, - name: "".to_owned(), - }; - - assert_eq!( - cake_model.find_fruit().build(MysqlQueryBuilder).to_string(), - [ - "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`", - "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`", - "WHERE `cake`.`id` = 12", - ] - .join(" ") - ); - } - #[test] fn alias_1() { assert_eq!(