diff --git a/src/query/join.rs b/src/query/join.rs index e71b7027..b0243c59 100644 --- a/src/query/join.rs +++ b/src/query/join.rs @@ -189,7 +189,7 @@ mod tests { assert_eq!( find_filling.build(DbBackend::MySql).to_string(), [ - "SELECT `filling`.`id`, `filling`.`name` FROM `filling`", + "SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id` FROM `filling`", "INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`", "INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`", ] @@ -248,7 +248,7 @@ mod tests { .build(DbBackend::MySql) .to_string(), [ - r#"SELECT `filling`.`id`, `filling`.`name`"#, + r#"SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id`"#, r#"FROM `filling`"#, 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`"#, @@ -260,6 +260,30 @@ mod tests { #[test] fn join_11() { + let cake_model = cake::Model { + id: 18, + name: "".to_owned(), + }; + + assert_eq!( + cake_model + .find_linked(cake::CakeToFillingVendor) + .build(DbBackend::MySql) + .to_string(), + [ + r#"SELECT `vendor`.`id`, `vendor`.`name`"#, + r#"FROM `vendor`"#, + r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#, + r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#, + r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id`"#, + r#"WHERE `r2`.`id` = 18"#, + ] + .join(" ") + ); + } + + #[test] + fn join_12() { assert_eq!( cake::Entity::find() .find_also_linked(cake::CakeToFilling) @@ -267,7 +291,7 @@ 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`"#, + r#"`filling`.`id` AS `B_id`, `filling`.`name` AS `B_name`, `filling`.`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`"#, @@ -275,4 +299,23 @@ mod tests { .join(" ") ); } + + #[test] + fn join_13() { + assert_eq!( + cake::Entity::find() + .find_also_linked(cake::CakeToFillingVendor) + .build(DbBackend::MySql) + .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#"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`"#, + ] + .join(" ") + ); + } } diff --git a/src/tests_cfg/cake.rs b/src/tests_cfg/cake.rs index 920e1fea..eb8c937e 100644 --- a/src/tests_cfg/cake.rs +++ b/src/tests_cfg/cake.rs @@ -47,4 +47,21 @@ impl Linked for CakeToFilling { } } +#[derive(Debug)] +pub struct CakeToFillingVendor; + +impl Linked for CakeToFillingVendor { + type FromEntity = Entity; + + type ToEntity = super::vendor::Entity; + + fn link(&self) -> Vec { + vec![ + super::cake_filling::Relation::Cake.def().rev(), + super::cake_filling::Relation::Filling.def(), + super::filling::Relation::Vendor.def(), + ] + } +} + impl ActiveModelBehavior for ActiveModel {} diff --git a/src/tests_cfg/filling.rs b/src/tests_cfg/filling.rs index 14f7a849..4de591c5 100644 --- a/src/tests_cfg/filling.rs +++ b/src/tests_cfg/filling.rs @@ -9,6 +9,7 @@ pub struct Entity; pub struct Model { pub id: i32, pub name: String, + pub vendor_id: Option, #[sea_orm(ignore)] pub ignored_attr: i32, } @@ -18,6 +19,7 @@ pub struct Model { pub enum Column { Id, Name, + VendorId, } // Then, customize each column names here. @@ -46,7 +48,9 @@ impl PrimaryKeyTrait for PrimaryKey { } #[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} +pub enum Relation { + Vendor, +} impl ColumnTrait for Column { type EntityName = Entity; @@ -55,13 +59,19 @@ impl ColumnTrait for Column { match self { Self::Id => ColumnType::Integer.def(), Self::Name => ColumnType::String(None).def(), + Self::VendorId => ColumnType::Integer.def().nullable(), } } } impl RelationTrait for Relation { fn def(&self) -> RelationDef { - panic!() + match self { + Self::Vendor => Entity::belongs_to(super::vendor::Entity) + .from(Column::VendorId) + .to(super::vendor::Column::Id) + .into(), + } } } diff --git a/src/tests_cfg/mod.rs b/src/tests_cfg/mod.rs index 81d553ac..9e5d4de0 100644 --- a/src/tests_cfg/mod.rs +++ b/src/tests_cfg/mod.rs @@ -6,6 +6,7 @@ pub mod cake_filling; pub mod cake_filling_price; pub mod filling; pub mod fruit; +pub mod vendor; pub use cake::Entity as Cake; pub use cake_expanded::Entity as CakeExpanded; @@ -13,3 +14,4 @@ pub use cake_filling::Entity as CakeFilling; pub use cake_filling_price::Entity as CakeFillingPrice; pub use filling::Entity as Filling; pub use fruit::Entity as Fruit; +pub use vendor::Entity as Vendor; diff --git a/src/tests_cfg/vendor.rs b/src/tests_cfg/vendor.rs new file mode 100644 index 00000000..12b6affb --- /dev/null +++ b/src/tests_cfg/vendor.rs @@ -0,0 +1,27 @@ +use crate as sea_orm; +use crate::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "vendor")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::filling::Relation::Vendor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {}