Skip to content

Commit e16eef4

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

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-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

+35-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,38 @@ 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 link = l.link();
48+
let tbl_alias = &format!("r{}", link.len() - 1);
49+
let mut cte_query = l.find_linked().belongs_to_tbl_alias(self, tbl_alias).query;
50+
51+
let mut last = link.pop().expect("non-zero links");
52+
last.from_tbl = cte_name.clone().into_table_ref();
53+
link.push(last);
54+
let recursive_query: Select<L::ToEntity> =
55+
find_linked(link.into_iter(), JoinType::InnerJoin);
56+
57+
cte_query.union(UnionType::All, recursive_query.into_query());
58+
let cte = CommonTableExpression::new()
59+
.table_name(cte_name.clone())
60+
.query(cte_query)
61+
.to_owned();
62+
63+
let mut select = Self::Entity::find();
64+
select
65+
.query
66+
.from_clear()
67+
.from_as(cte_name, Self::Entity::default())
68+
.with_cte(cte);
69+
select
70+
}
71+
4072
/// Delete a model
4173
async fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
4274
where

0 commit comments

Comments
 (0)