From 01eff84ce8eef6d93e887002474b6a1419c7c70d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 13 Oct 2021 20:56:05 +0800 Subject: [PATCH] Join with table alias --- src/query/combine.rs | 7 ++++-- src/query/join.rs | 51 ++++++++++++++++++++++++++++++--------- tests/relational_tests.rs | 12 ++++++--- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/query/combine.rs b/src/query/combine.rs index 0c0f151f..c03906ea 100644 --- a/src/query/combine.rs +++ b/src/query/combine.rs @@ -31,7 +31,7 @@ impl Select where E: EntityTrait, { - 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) => { @@ -77,11 +77,14 @@ where F: EntityTrait, { pub(crate) fn new(query: SelectStatement) -> Self { + Self::new_without_prepare(query).prepare_select() + } + + pub(crate) fn new_without_prepare(query: SelectStatement) -> Self { Self { query, entity: PhantomData, } - .prepare_select() } fn prepare_select(mut self) -> Self { diff --git a/src/query/join.rs b/src/query/join.rs index 50592933..8fb4e0e6 100644 --- a/src/query/join.rs +++ b/src/query/join.rs @@ -1,5 +1,9 @@ -use crate::{EntityTrait, Linked, QuerySelect, Related, Select, SelectTwo, SelectTwoMany}; +use crate::{ + join_tbl_on_condition, unpack_table_ref, EntityTrait, IdenStatic, Iterable, Linked, + QuerySelect, Related, Select, SelectA, SelectB, SelectTwo, SelectTwoMany, +}; pub use sea_query::JoinType; +use sea_query::{Alias, Expr, IntoIden, SeaRc, SelectExpr}; impl Select where @@ -65,10 +69,35 @@ where T: EntityTrait, { let mut slf = self; - for rel in l.link() { - slf = slf.join(JoinType::LeftJoin, rel); + for (i, rel) in l.link().into_iter().enumerate() { + let to_tbl = Alias::new(&format!("r{}", i)).into_iden(); + let from_tbl = if i > 0 { + Alias::new(&format!("r{}", i - 1)).into_iden() + } else { + unpack_table_ref(&rel.from_tbl) + }; + + slf.query().join_as( + JoinType::LeftJoin, + unpack_table_ref(&rel.to_tbl), + SeaRc::clone(&to_tbl), + join_tbl_on_condition(from_tbl, to_tbl, rel.from_col, rel.to_col), + ); } - slf.select_also(T::default()) + slf = slf.apply_alias(SelectA.as_str()); + let mut select_two = SelectTwo::new_without_prepare(slf.query); + for col in ::iter() { + let alias = format!("{}{}", SelectB.as_str(), col.as_str()); + select_two.query().expr(SelectExpr { + expr: Expr::tbl( + Alias::new(&format!("r{}", l.link().len() - 1)).into_iden(), + col.into_iden(), + ) + .into(), + alias: Some(SeaRc::new(Alias::new(&alias))), + }); + } + select_two } } @@ -291,10 +320,10 @@ mod tests { .to_string(), [ r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#, - r#"`filling`.`id` AS `B_id`, `filling`.`name` AS `B_name`, `filling`.`vendor_id` AS `B_vendor_id`"#, + r#"`r1`.`id` AS `B_id`, `r1`.`name` AS `B_name`, `r1`.`vendor_id` AS `B_vendor_id`"#, r#"FROM `cake`"#, - r#"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#, - r#"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#, + r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#, + r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#, ] .join(" ") ); @@ -309,11 +338,11 @@ mod tests { .to_string(), [ r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#, - r#"`vendor`.`id` AS `B_id`, `vendor`.`name` AS `B_name`"#, + r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#, r#"FROM `cake`"#, - r#"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#, - r#"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#, - r#"LEFT JOIN `vendor` ON `filling`.`vendor_id` = `vendor`.`id`"#, + r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#, + r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#, + r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#, ] .join(" ") ); diff --git a/tests/relational_tests.rs b/tests/relational_tests.rs index 9778e4c0..ed5e92f5 100644 --- a/tests/relational_tests.rs +++ b/tests/relational_tests.rs @@ -490,6 +490,7 @@ pub async fn having() { pub async fn linked() -> Result<(), DbErr> { use common::bakery_chain::Order; use sea_orm::{SelectA, SelectB}; + use sea_query::{Alias, Expr}; let ctx = TestContext::new("test_linked").await; create_tables(&ctx.db).await?; @@ -673,13 +674,16 @@ pub async fn linked() -> Result<(), DbErr> { .find_also_linked(baker::BakedForCustomer) .select_only() .column_as(baker::Column::Name, (SelectA, baker::Column::Name)) - .column_as(customer::Column::Name, (SelectB, customer::Column::Name)) + .column_as( + Expr::tbl(Alias::new("r4"), customer::Column::Name).into_simple_expr(), + (SelectB, customer::Column::Name), + ) .group_by(baker::Column::Id) - .group_by(customer::Column::Id) + .group_by(Expr::tbl(Alias::new("r4"), customer::Column::Id).into_simple_expr()) .group_by(baker::Column::Name) - .group_by(customer::Column::Name) + .group_by(Expr::tbl(Alias::new("r4"), customer::Column::Name).into_simple_expr()) .order_by_asc(baker::Column::Id) - .order_by_asc(customer::Column::Id) + .order_by_asc(Expr::tbl(Alias::new("r4"), customer::Column::Id).into_simple_expr()) .into_model() .all(&ctx.db) .await?;