find_linked
join with table alias
This commit is contained in:
parent
1eb0e5cbb2
commit
ee504e7d9f
@ -1,5 +1,7 @@
|
||||
use crate::{EntityTrait, QuerySelect, RelationDef, Select};
|
||||
use sea_query::JoinType;
|
||||
use crate::{
|
||||
join_tbl_on_condition, unpack_table_ref, EntityTrait, QuerySelect, RelationDef, Select,
|
||||
};
|
||||
use sea_query::{Alias, IntoIden, JoinType, SeaRc};
|
||||
|
||||
pub type LinkDef = RelationDef;
|
||||
|
||||
@ -12,8 +14,20 @@ pub trait Linked {
|
||||
|
||||
fn find_linked(&self) -> Select<Self::ToEntity> {
|
||||
let mut select = Select::new();
|
||||
for rel in self.link().into_iter().rev() {
|
||||
select = select.join_rev(JoinType::InnerJoin, rel);
|
||||
for (i, rel) in self.link().into_iter().rev().enumerate() {
|
||||
let from_tbl = Alias::new(&format!("r{}", i)).into_iden();
|
||||
let to_tbl = if i > 0 {
|
||||
Alias::new(&format!("r{}", i - 1)).into_iden()
|
||||
} else {
|
||||
unpack_table_ref(&rel.to_tbl)
|
||||
};
|
||||
|
||||
select.query().join_as(
|
||||
JoinType::InnerJoin,
|
||||
unpack_table_ref(&rel.from_tbl),
|
||||
SeaRc::clone(&from_tbl),
|
||||
join_tbl_on_condition(from_tbl, to_tbl, rel.from_col, rel.to_col),
|
||||
);
|
||||
}
|
||||
select
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ pub trait ModelTrait: Clone + Send + Debug {
|
||||
where
|
||||
L: Linked<FromEntity = Self::Entity>,
|
||||
{
|
||||
l.find_linked().belongs_to(self)
|
||||
let tbl_alias = &format!("r{}", l.link().len() - 1);
|
||||
l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@ use crate::{
|
||||
ColumnTrait, EntityTrait, Identity, IntoIdentity, IntoSimpleExpr, Iterable, ModelTrait,
|
||||
PrimaryKeyToColumn, RelationDef,
|
||||
};
|
||||
pub use sea_query::{Condition, ConditionalStatement, DynIden, JoinType, Order, OrderedStatement};
|
||||
use sea_query::{
|
||||
Expr, IntoCondition, LockType, SeaRc, SelectExpr, SelectStatement, SimpleExpr, TableRef,
|
||||
Alias, Expr, Iden, IntoCondition, LockType, SeaRc, SelectExpr, SelectStatement, SimpleExpr,
|
||||
TableRef,
|
||||
};
|
||||
pub use sea_query::{Condition, ConditionalStatement, DynIden, JoinType, Order, OrderedStatement};
|
||||
|
||||
// LINT: when the column does not appear in tables selected from
|
||||
// LINT: when there is a group by clause, but some columns don't have aggregate functions
|
||||
@ -287,14 +288,35 @@ pub trait QueryFilter: Sized {
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn belongs_to_tbl_alias<M>(mut self, model: &M, tbl_alias: &str) -> Self
|
||||
where
|
||||
M: ModelTrait,
|
||||
{
|
||||
for key in <M::Entity as EntityTrait>::PrimaryKey::iter() {
|
||||
let col = key.into_column();
|
||||
let expr = Expr::tbl(Alias::new(tbl_alias), col).eq(model.get(col));
|
||||
self = self.filter(expr);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn join_condition(rel: RelationDef) -> SimpleExpr {
|
||||
pub(crate) fn join_condition(rel: RelationDef) -> SimpleExpr {
|
||||
let from_tbl = unpack_table_ref(&rel.from_tbl);
|
||||
let to_tbl = unpack_table_ref(&rel.to_tbl);
|
||||
let owner_keys = rel.from_col;
|
||||
let foreign_keys = rel.to_col;
|
||||
|
||||
join_tbl_on_condition(from_tbl, to_tbl, owner_keys, foreign_keys)
|
||||
}
|
||||
|
||||
pub(crate) fn join_tbl_on_condition(
|
||||
from_tbl: SeaRc<dyn Iden>,
|
||||
to_tbl: SeaRc<dyn Iden>,
|
||||
owner_keys: Identity,
|
||||
foreign_keys: Identity,
|
||||
) -> SimpleExpr {
|
||||
match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(SeaRc::clone(&from_tbl), o1).equals(SeaRc::clone(&to_tbl), f1)
|
||||
|
@ -76,6 +76,7 @@ where
|
||||
mod tests {
|
||||
use crate::tests_cfg::{cake, cake_filling, cake_filling_price, filling, fruit};
|
||||
use crate::{ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QueryTrait};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn join_1() {
|
||||
@ -249,9 +250,9 @@ mod tests {
|
||||
[
|
||||
r#"SELECT `filling`.`id`, `filling`.`name`"#,
|
||||
r#"FROM `filling`"#,
|
||||
r#"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
|
||||
r#"INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
|
||||
r#"WHERE `cake`.`id` = 12"#,
|
||||
r#"INNER JOIN `cake_filling` AS `r0` ON `r0`.`filling_id` = `filling`.`id`"#,
|
||||
r#"INNER JOIN `cake` AS `r1` ON `r1`.`id` = `r0`.`cake_id`"#,
|
||||
r#"WHERE `r1`.`id` = 12"#,
|
||||
]
|
||||
.join(" ")
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user