use crate::{EntityTrait, Identity, IdentityOf, Iterable, QuerySelect, Select}; use core::marker::PhantomData; use sea_query::{DynIden, IntoIden, JoinType}; use std::fmt::Debug; #[derive(Clone, Debug)] pub enum RelationType { HasOne, HasMany, } pub trait RelationTrait: Iterable + Debug + 'static { fn def(&self) -> RelationDef; } pub trait Related where R: EntityTrait, { fn to() -> RelationDef; fn via() -> Option { None } fn find_related() -> Select { Select::::new().join_join_rev(JoinType::InnerJoin, Self::to(), Self::via()) } } pub struct RelationDef { pub rel_type: RelationType, pub from_tbl: DynIden, pub to_tbl: DynIden, pub from_col: Identity, pub to_col: Identity, } pub struct RelationBuilder where E: EntityTrait, R: EntityTrait, { entities: PhantomData<(E, R)>, rel_type: RelationType, from_tbl: DynIden, to_tbl: DynIden, from_col: Option, to_col: Option, } impl RelationDef { /// Reverse this relation (swap from and to) pub fn rev(self) -> Self { Self { rel_type: self.rel_type, from_tbl: self.to_tbl, to_tbl: self.from_tbl, from_col: self.to_col, to_col: self.from_col, } } } impl RelationBuilder where E: EntityTrait, R: EntityTrait, { pub(crate) fn new(rel_type: RelationType, from: E, to: R) -> Self { Self { entities: PhantomData, rel_type, from_tbl: from.into_iden(), to_tbl: to.into_iden(), from_col: None, to_col: None, } } pub(crate) fn from_rel(rel_type: RelationType, rel: RelationDef) -> Self { Self { entities: PhantomData, rel_type, from_tbl: rel.from_tbl, to_tbl: rel.to_tbl, from_col: Some(rel.from_col), to_col: Some(rel.to_col), } } pub fn from(mut self, identifier: T) -> Self where T: IdentityOf, { self.from_col = Some(identifier.identity_of()); self } pub fn to(mut self, identifier: T) -> Self where T: IdentityOf, { self.to_col = Some(identifier.identity_of()); self } } impl From> for RelationDef where E: EntityTrait, R: EntityTrait, { fn from(b: RelationBuilder) -> Self { RelationDef { rel_type: b.rel_type, from_tbl: b.from_tbl, to_tbl: b.to_tbl, from_col: b.from_col.unwrap(), to_col: b.to_col.unwrap(), } } }