WIP: Linked (#89)

This commit is contained in:
Billy Chan 2021-08-23 23:11:08 +08:00
parent 8cfa14233d
commit 31941d3af6
No known key found for this signature in database
GPG Key ID: A2D690CAC7DF3CC7
6 changed files with 97 additions and 6 deletions

View File

@ -1,6 +1,6 @@
use std::str::FromStr;
use crate::{EntityName, IdenStatic, Iterable};
use sea_query::{DynIden, Expr, SeaRc, SelectStatement, SimpleExpr, Value};
use std::str::FromStr;
#[derive(Debug, Clone)]
pub struct ColumnDef {

View File

@ -1,4 +1,4 @@
use crate::{DbErr, EntityTrait, QueryFilter, QueryResult, Related, Select};
use crate::{DbErr, EntityTrait, Linked, QueryFilter, QueryResult, Related, Select};
pub use sea_query::Value;
use std::fmt::Debug;
@ -16,6 +16,13 @@ pub trait ModelTrait: Clone + Debug {
{
<Self::Entity as Related<R>>::find_related().belongs_to(self)
}
fn find_linked<L>(&self, _: L) -> Select<L::ToEntity>
where
L: Linked<FromEntity = Self::Entity>,
{
L::find_linked()
}
}
pub trait FromQueryResult {

View File

@ -1,9 +1,9 @@
pub use crate::{
error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType,
DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity,
DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, Iden, IdenStatic, ModelTrait,
PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef,
RelationTrait, Select, Value,
DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, Iden, IdenStatic, Linked,
ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult, Related,
RelationDef, RelationTrait, Select, Value,
};
#[cfg(feature = "with-json")]

View File

@ -28,6 +28,22 @@ where
}
}
pub trait Linked {
type FromEntity: EntityTrait;
type ToEntity: EntityTrait;
fn link() -> Vec<RelationDef>;
fn find_linked() -> Select<Self::ToEntity> {
let mut select = Select::new();
for rel in Self::link() {
select = select.join(JoinType::InnerJoin, rel);
}
select
}
}
pub struct RelationDef {
pub rel_type: RelationType,
pub from_tbl: TableRef,

View File

@ -1,4 +1,4 @@
use crate::{EntityTrait, QuerySelect, Related, Select, SelectTwo, SelectTwoMany};
use crate::{EntityTrait, Linked, QuerySelect, Related, Select, SelectTwo, SelectTwoMany};
pub use sea_query::JoinType;
impl<E> Select<E>
@ -57,6 +57,19 @@ where
{
self.left_join(r).select_with(r)
}
/// Left Join with a Linked Entity and select both Entity.
pub fn find_also_linked<L, T>(self, _: L) -> SelectTwo<E, T>
where
L: Linked<FromEntity = E, ToEntity = T>,
T: EntityTrait,
{
let mut slf = self;
for rel in L::link() {
slf = slf.join(JoinType::LeftJoin, rel);
}
slf.select_also(T::default())
}
}
#[cfg(test)]
@ -220,4 +233,44 @@ mod tests {
.join(" ")
);
}
#[test]
fn join_10() {
let cake_model = cake::Model {
id: 12,
name: "".to_owned(),
};
assert_eq!(
cake_model
.find_linked(cake::CakeToFilling)
.build(DbBackend::MySql)
.to_string(),
[
r#"SELECT `filling`.`id`, `filling`.`name`"#,
r#"FROM `filling`"#,
r#"INNER JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
r#"INNER JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
]
.join(" ")
);
}
#[test]
fn join_11() {
assert_eq!(
cake::Entity::find()
.find_also_linked(cake::CakeToFilling)
.build(DbBackend::MySql)
.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#"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`"#,
]
.join(" ")
);
}
}

View File

@ -73,4 +73,19 @@ impl Related<super::filling::Entity> for Entity {
}
}
pub struct CakeToFilling;
impl Linked for CakeToFilling {
type FromEntity = Entity;
type ToEntity = super::filling::Entity;
fn link() -> Vec<RelationDef> {
vec![
super::cake_filling::Relation::Cake.def().rev(),
super::cake_filling::Relation::Filling.def(),
]
}
}
impl ActiveModelBehavior for ActiveModel {}