Move code

This commit is contained in:
Chris Tsang 2021-05-15 13:15:43 +08:00
parent 2a2e5d6ba6
commit 9dc7c818d7
8 changed files with 390 additions and 333 deletions

View File

@ -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_cake;
mod example_fruit; mod example_fruit;

View File

@ -3,7 +3,7 @@ use sea_query::{QueryBuilder, SelectStatement};
use std::marker::PhantomData; use std::marker::PhantomData;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SingleSelect<M> pub struct SelectModel<M>
where where
M: FromQueryResult, M: FromQueryResult,
{ {
@ -12,7 +12,7 @@ where
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DoubleSelect<M, N> pub struct SelectTwoModel<M, N>
where where
M: FromQueryResult, M: FromQueryResult,
N: FromQueryResult, N: FromQueryResult,
@ -25,11 +25,11 @@ impl<E: 'static> Select<E>
where where
E: EntityTrait, E: EntityTrait,
{ {
pub fn into_model<M>(self) -> SingleSelect<M> pub fn into_model<M>(self) -> SelectModel<M>
where where
M: FromQueryResult, M: FromQueryResult,
{ {
SingleSelect { SelectModel {
query: self.query, query: self.query,
model: PhantomData, model: PhantomData,
} }
@ -44,7 +44,7 @@ where
} }
} }
impl<M> SingleSelect<M> impl<M> SelectModel<M>
where where
M: FromQueryResult, M: FromQueryResult,
{ {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
ColumnTrait, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, RelationBuilder, RelationTrait, ColumnTrait, ModelTrait, PrimaryKeyOfModel, PrimaryKeyTrait, QueryHelper, RelationBuilder,
RelationType, Select, SelectQuery, RelationTrait, RelationType, Select,
}; };
use sea_query::{Iden, IntoIden, Value}; use sea_query::{Iden, IntoIden, Value};
use std::fmt::Debug; use std::fmt::Debug;

View File

@ -57,7 +57,7 @@ pub trait ColumnTrait: IdenStatic {
bind_oper!(lte); 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// 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!( /// assert_eq!(
/// cake::Entity::find() /// cake::Entity::find()

140
src/query/helper.rs Normal file
View File

@ -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<C>(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<C>(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<C>(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<C>(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<C>(mut self, col: C) -> Self
where
C: IntoSimpleExpr,
{
self.query()
.order_by_expr(col.into_simple_expr(), Order::Desc);
self
}
}

197
src/query/join.rs Normal file
View File

@ -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<E> Select<E>
where
E: EntityTrait,
{
pub fn belongs_to<R>(self, model: &R::Model) -> Self
where
R: EntityTrait + Related<E>,
R::PrimaryKey: PrimaryKeyOfModel<R::Model>,
{
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<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::LeftJoin, E::to())
}
/// Right Join with a Related Entity.
pub fn right_join<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::RightJoin, E::to())
}
/// Inner Join with a Related Entity.
pub fn inner_join<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::InnerJoin, E::to())
}
/// Join with an Entity Related to me.
pub fn reverse_join<R>(self, _: R) -> Self
where
R: EntityTrait + Related<E>,
{
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<fruit::Entity> = 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`",
);
}
}

View File

@ -1,5 +1,9 @@
mod helper;
mod join;
mod result; mod result;
mod select; mod select;
pub use helper::*;
pub use join::*;
pub use result::*; pub use result::*;
pub use select::*; pub use select::*;

View File

@ -1,13 +1,9 @@
use crate::{ use crate::{ColumnTrait, EntityTrait, Iterable, QueryHelper, Statement};
ColumnTrait, EntityTrait, Identity, Iterable, ModelTrait, PrimaryKeyOfModel, Related,
RelationDef, Statement,
};
use core::fmt::Debug; use core::fmt::Debug;
use core::marker::PhantomData; use core::marker::PhantomData;
pub use sea_query::JoinType; pub use sea_query::JoinType;
use sea_query::{ use sea_query::{
Alias, ColumnRef, Expr, Iden, IntoColumnRef, IntoIden, Order, QueryBuilder, SelectExpr, Alias, ColumnRef, Iden, IntoColumnRef, IntoIden, QueryBuilder, SelectStatement, SimpleExpr,
SelectStatement, SimpleExpr,
}; };
use std::rc::Rc; use std::rc::Rc;
@ -20,10 +16,39 @@ where
pub(crate) entity: PhantomData<E>, pub(crate) entity: PhantomData<E>,
} }
#[derive(Clone, Debug)]
pub struct SelectTwo<E, F>
where
E: EntityTrait,
F: EntityTrait,
{
pub(crate) query: SelectStatement,
pub(crate) entity: PhantomData<(E, F)>,
}
pub trait IntoSimpleExpr { pub trait IntoSimpleExpr {
fn into_simple_expr(self) -> SimpleExpr; fn into_simple_expr(self) -> SimpleExpr;
} }
impl<E> QueryHelper for Select<E>
where
E: EntityTrait,
{
fn query(&mut self) -> &mut SelectStatement {
&mut self.query
}
}
impl<E, F> QueryHelper for SelectTwo<E, F>
where
E: EntityTrait,
F: EntityTrait,
{
fn query(&mut self) -> &mut SelectStatement {
&mut self.query
}
}
impl<C> IntoSimpleExpr for C impl<C> IntoSimpleExpr for C
where where
C: ColumnTrait, C: ColumnTrait,
@ -67,7 +92,7 @@ where
self 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| { self.query().exprs_mut_for_each(|sel| {
match &sel.alias { match &sel.alias {
Some(alias) => { Some(alias) => {
@ -90,87 +115,6 @@ where
self self
} }
pub fn belongs_to<R>(self, model: &R::Model) -> Self
where
R: EntityTrait + Related<E>,
R::PrimaryKey: PrimaryKeyOfModel<R::Model>,
{
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<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::LeftJoin, E::to())
}
/// Right Join with a Related Entity.
pub fn right_join<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::RightJoin, E::to())
}
/// Inner Join with a Related Entity.
pub fn inner_join<R>(self, _: R) -> Self
where
R: EntityTrait,
E: Related<R>,
{
self.join(JoinType::InnerJoin, E::to())
}
/// Join with an Entity Related to me.
pub fn reverse_join<R>(self, _: R) -> Self
where
R: EntityTrait + Related<E>,
{
self.join_rev(JoinType::InnerJoin, R::to())
}
/// Get a mutable ref to the query builder /// Get a mutable ref to the query builder
pub fn query(&mut self) -> &mut SelectStatement { pub fn query(&mut self) -> &mut SelectStatement {
&mut self.query &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<C>(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<C>(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<C>(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<C>(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<C>(mut self, col: C) -> Self
where
C: IntoSimpleExpr,
{
self.query()
.order_by_expr(col.into_simple_expr(), Order::Desc);
self
}
}
impl<E> SelectQuery for Select<E>
where
E: EntityTrait,
{
fn query(&mut self) -> &mut SelectStatement {
&mut self.query
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tests_cfg::{cake, fruit}; use crate::tests_cfg::cake;
use crate::{ColumnTrait, EntityTrait, SelectQuery}; use crate::{EntityTrait, QueryHelper};
use sea_query::MysqlQueryBuilder; 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<fruit::Entity> = 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] #[test]
fn alias_1() { fn alias_1() {
assert_eq!( assert_eq!(