Skip to content

Commit 5cc03a3

Browse files
committed
Add find_linked_recursive method to ModelTrait
1 parent 4809cc6 commit 5cc03a3

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/entity/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub trait Linked {
3131
}
3232
}
3333

34-
fn find_linked<I, E>(links: I, join: JoinType) -> Select<E>
34+
pub(crate) fn find_linked<I, E>(links: I, join: JoinType) -> Select<E>
3535
where
3636
I: Iterator<Item = LinkDef>,
3737
E: EntityTrait,

src/entity/model.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
2-
ActiveModelBehavior, ActiveModelTrait, ConnectionTrait, DbErr, DeleteResult, EntityTrait,
3-
IntoActiveModel, Linked, QueryFilter, QueryResult, Related, Select, SelectModel, SelectorRaw,
4-
Statement,
2+
find_linked, ActiveModelBehavior, ActiveModelTrait, ConnectionTrait, DbErr, DeleteResult,
3+
EntityTrait, IntoActiveModel, Linked, QueryFilter, QueryResult, QueryTrait, Related, Select,
4+
SelectModel, SelectorRaw, Statement,
55
};
66
use async_trait::async_trait;
77
pub use sea_query::{Alias, CommonTableExpression, IntoTableRef, JoinType, UnionType, Value};
@@ -37,6 +37,40 @@ pub trait ModelTrait: Clone + Send + Debug {
3737
l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
3838
}
3939

40+
/// Find linked Models, recursively
41+
fn find_linked_recursive<L>(&self, l: L) -> Select<L::ToEntity>
42+
where
43+
L: Linked<FromEntity = Self::Entity, ToEntity = Self::Entity>,
44+
{
45+
let cte_name = Alias::new("cte");
46+
47+
let mut select = Self::Entity::find();
48+
49+
let mut link = l.link();
50+
let Some(last) = link.last_mut() else {
51+
return select;
52+
};
53+
last.from_tbl = cte_name.clone().into_table_ref();
54+
55+
let recursive_query: Select<L::ToEntity> =
56+
find_linked(link.into_iter().rev(), JoinType::InnerJoin);
57+
58+
let mut cte_query = self.find_linked(l).query;
59+
cte_query.union(UnionType::All, recursive_query.into_query());
60+
61+
let cte = CommonTableExpression::new()
62+
.table_name(cte_name.clone())
63+
.query(cte_query)
64+
.to_owned();
65+
66+
select
67+
.query
68+
.from_clear()
69+
.from_as(cte_name, Self::Entity::default())
70+
.with_cte(cte);
71+
select
72+
}
73+
4074
/// Delete a model
4175
async fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
4276
where

0 commit comments

Comments
 (0)