|
1 | 1 | 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, |
5 | 5 | };
|
6 | 6 | use async_trait::async_trait;
|
7 | 7 | pub use sea_query::{Alias, CommonTableExpression, IntoTableRef, JoinType, UnionType, Value};
|
@@ -37,6 +37,38 @@ pub trait ModelTrait: Clone + Send + Debug {
|
37 | 37 | l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
|
38 | 38 | }
|
39 | 39 |
|
| 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 | + |
40 | 72 | /// Delete a model
|
41 | 73 | async fn delete<'a, A, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
|
42 | 74 | where
|
|
0 commit comments