diff --git a/src/entity/base.rs b/src/entity/base.rs index dcaf95e7..dc8af526 100644 --- a/src/entity/base.rs +++ b/src/entity/base.rs @@ -49,7 +49,7 @@ pub trait EntityTrait: Iden + Default + Debug + 'static { /// ); /// ``` fn find() -> Select { - Select::new(Self::default()) + Select::::new() } /// ``` diff --git a/src/entity/relation.rs b/src/entity/relation.rs index 8f7f9011..bd9f2757 100644 --- a/src/entity/relation.rs +++ b/src/entity/relation.rs @@ -1,4 +1,4 @@ -use super::{Identity, IntoIdentity}; +use crate::{EntityTrait, Identity, IntoIdentity, Select}; use sea_query::{Iden, IntoIden}; use std::fmt::Debug; use std::rc::Rc; @@ -14,6 +14,17 @@ pub trait RelationTrait: Debug + 'static { fn rel_def(&self) -> RelationDef; } +pub trait Related +where + R: EntityTrait, +{ + fn via() -> RelationDef; + + fn find_related() -> Select { + Select::::new().prepare_reverse_join(Self::via()) + } +} + pub struct RelationDef { pub rel_type: RelationType, pub from_tbl: Rc, diff --git a/src/query/select.rs b/src/query/select.rs index ca273312..856b3509 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -18,7 +18,7 @@ impl Select where E: EntityTrait, { - pub(crate) fn new(_: E) -> Self { + pub(crate) fn new() -> Self { Self { query: SelectStatement::new(), entity: PhantomData, @@ -56,11 +56,7 @@ where self } - pub fn reverse_join(mut self, rel: R) -> Self - where - R: RelationTrait, - { - let rel = rel.rel_def(); + pub(crate) fn prepare_reverse_join(mut self, rel: RelationDef) -> Self { let from_tbl = rel.from_tbl.clone(); let to_tbl = rel.to_tbl.clone(); let owner_keys = rel.from_col; @@ -135,6 +131,13 @@ where self.prepare_join(JoinType::InnerJoin, E::Relation::rel_def(&rel)) } + pub fn reverse_join(self, rel: R) -> Self + where + R: RelationTrait, + { + self.prepare_reverse_join(rel.rel_def()) + } + /// Get a mutable ref to the query builder pub fn query(&mut self) -> &mut SelectStatement { &mut self.query @@ -211,4 +214,20 @@ mod tests { .join(" ") ); } + + #[test] + fn join_4() { + assert_eq!( + cake::Entity::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(" ") + ); + } } diff --git a/src/tests_cfg/cake.rs b/src/tests_cfg/cake.rs index 06cc13bb..fd5323b8 100644 --- a/src/tests_cfg/cake.rs +++ b/src/tests_cfg/cake.rs @@ -1,6 +1,6 @@ use crate::{ ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait, - QueryResult, RelationDef, RelationTrait, TypeErr, + QueryResult, Related, RelationDef, RelationTrait, Select, TypeErr, }; #[derive(Default, Debug, Iden)] @@ -66,3 +66,15 @@ impl RelationTrait for Relation { } } } + +impl Related for Entity { + fn via() -> RelationDef { + Relation::Fruit.rel_def() + } +} + +impl Entity { + pub fn find_fruit() -> Select { + Self::find_related() + } +}