Skip to main content

sea_orm/executor/select/
four.rs

1use super::*;
2use crate::{
3    JoinType, Paginator, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, QueryTrait, Related,
4    SelectC, SelectFive, SelectFour, SelectFourMany, Topology, TopologyStar,
5    combine::{SelectD, prepare_select_col},
6};
7
8impl<E, F, G, H, TOP> SelectFour<E, F, G, H, TOP>
9where
10    E: EntityTrait,
11    F: EntityTrait,
12    G: EntityTrait,
13    H: EntityTrait,
14    TOP: Topology,
15{
16    pub(crate) fn new(query: SelectStatement) -> Self {
17        Self::new_without_prepare(query).prepare_select()
18    }
19
20    pub(crate) fn new_without_prepare(query: SelectStatement) -> Self {
21        Self {
22            query,
23            entity: PhantomData,
24        }
25    }
26
27    fn prepare_select(mut self) -> Self {
28        prepare_select_col::<H, _, _>(&mut self, SelectD);
29        self
30    }
31
32    /// Left Join with a Related Entity and select all Entities.
33    pub fn find_also<T, I>(self, _: T, _: I) -> SelectFive<E, F, G, H, I, TopologyStar>
34    where
35        I: EntityTrait,
36        T: EntityTrait + Related<I>,
37    {
38        SelectFive::new(
39            self.join_join(JoinType::LeftJoin, T::to(), T::via())
40                .into_query(),
41        )
42    }
43}
44
45macro_rules! impl_query_trait {
46    ( $trait: ident ) => {
47        impl<E, F, G, H, TOP> $trait for SelectFour<E, F, G, H, TOP>
48        where
49            E: EntityTrait,
50            F: EntityTrait,
51            G: EntityTrait,
52            H: EntityTrait,
53            TOP: Topology,
54        {
55            type QueryStatement = SelectStatement;
56
57            fn query(&mut self) -> &mut SelectStatement {
58                &mut self.query
59            }
60        }
61    };
62}
63
64impl<E, F, G, H, TOP> QueryTrait for SelectFour<E, F, G, H, TOP>
65where
66    E: EntityTrait,
67    F: EntityTrait,
68    G: EntityTrait,
69    H: EntityTrait,
70    TOP: Topology,
71{
72    type QueryStatement = SelectStatement;
73    fn query(&mut self) -> &mut SelectStatement {
74        &mut self.query
75    }
76    fn as_query(&self) -> &SelectStatement {
77        &self.query
78    }
79    fn into_query(self) -> SelectStatement {
80        self.query
81    }
82}
83
84impl_query_trait!(QuerySelect);
85impl_query_trait!(QueryFilter);
86impl_query_trait!(QueryOrder);
87
88impl<M, N, O, P> SelectorTrait for SelectFourModel<M, N, O, P>
89where
90    M: FromQueryResult + Sized,
91    N: FromQueryResult + Sized,
92    O: FromQueryResult + Sized,
93    P: FromQueryResult + Sized,
94{
95    type Item = (M, Option<N>, Option<O>, Option<P>);
96
97    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
98        Ok((
99            M::from_query_result(&res, SelectA.as_str())?,
100            N::from_query_result_optional(&res, SelectB.as_str())?,
101            O::from_query_result_optional(&res, SelectC.as_str())?,
102            P::from_query_result_optional(&res, SelectD.as_str())?,
103        ))
104    }
105}
106
107impl<E, F, G, H, TOP> SelectFour<E, F, G, H, TOP>
108where
109    E: EntityTrait,
110    F: EntityTrait,
111    G: EntityTrait,
112    H: EntityTrait,
113    TOP: Topology,
114{
115    /// Perform a conversion into a [SelectFourModel]
116    pub fn into_model<M, N, O, P>(self) -> Selector<SelectFourModel<M, N, O, P>>
117    where
118        M: FromQueryResult,
119        N: FromQueryResult,
120        O: FromQueryResult,
121        P: FromQueryResult,
122    {
123        Selector {
124            query: self.query,
125            selector: PhantomData,
126        }
127    }
128
129    /// Perform a conversion into a [SelectFourModel] with [PartialModel](PartialModelTrait)
130    pub fn into_partial_model<M, N, O, P>(self) -> Selector<SelectFourModel<M, N, O, P>>
131    where
132        M: PartialModelTrait,
133        N: PartialModelTrait,
134        O: PartialModelTrait,
135        P: PartialModelTrait,
136    {
137        let select = QuerySelect::select_only(self);
138        let select = M::select_cols(select);
139        let select = N::select_cols(select);
140        let select = O::select_cols(select);
141        let select = P::select_cols(select);
142        select.into_model::<M, N, O, P>()
143    }
144
145    /// Convert the Models into JsonValue
146    #[cfg(feature = "with-json")]
147    pub fn into_json(
148        self,
149    ) -> Selector<SelectFourModel<JsonValue, JsonValue, JsonValue, JsonValue>> {
150        Selector {
151            query: self.query,
152            selector: PhantomData,
153        }
154    }
155
156    /// Get one Model from the Select query
157    pub async fn one<C>(
158        self,
159        db: &C,
160    ) -> Result<
161        Option<(
162            E::Model,
163            Option<F::Model>,
164            Option<G::Model>,
165            Option<H::Model>,
166        )>,
167        DbErr,
168    >
169    where
170        C: ConnectionTrait,
171    {
172        self.into_model().one(db).await
173    }
174
175    /// Get all Models from the Select query
176    pub async fn all<C>(
177        self,
178        db: &C,
179    ) -> Result<
180        Vec<(
181            E::Model,
182            Option<F::Model>,
183            Option<G::Model>,
184            Option<H::Model>,
185        )>,
186        DbErr,
187    >
188    where
189        C: ConnectionTrait,
190    {
191        self.into_model().all(db).await
192    }
193
194    /// Stream the results of a Select operation on a Model
195    #[cfg(feature = "stream")]
196    pub async fn stream<'a: 'b, 'b, C>(
197        self,
198        db: &'a C,
199    ) -> Result<
200        impl Stream<
201            Item = Result<
202                (
203                    E::Model,
204                    Option<F::Model>,
205                    Option<G::Model>,
206                    Option<H::Model>,
207                ),
208                DbErr,
209            >,
210        > + 'b,
211        DbErr,
212    >
213    where
214        C: ConnectionTrait + StreamTrait + Send,
215    {
216        self.into_model().stream(db).await
217    }
218
219    /// Stream the result of the operation with PartialModel
220    #[cfg(feature = "stream")]
221    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N, O, P>(
222        self,
223        db: &'a C,
224    ) -> Result<
225        impl Stream<Item = Result<(M, Option<N>, Option<O>, Option<P>), DbErr>> + 'b + Send,
226        DbErr,
227    >
228    where
229        C: ConnectionTrait + StreamTrait + Send,
230        M: PartialModelTrait + Send + 'b,
231        N: PartialModelTrait + Send + 'b,
232        O: PartialModelTrait + Send + 'b,
233        P: PartialModelTrait + Send + 'b,
234    {
235        self.into_partial_model().stream(db).await
236    }
237}
238
239impl<E, F, G, H, TOP> SelectFour<E, F, G, H, TOP>
240where
241    E: EntityTrait,
242    F: EntityTrait,
243    G: EntityTrait,
244    H: EntityTrait,
245    TOP: Topology,
246{
247    /// Consolidate query result by first model. Only the star topology
248    /// (E -> F, E -> G, E -> H) provides an `all()` impl.
249    pub fn consolidate(self) -> SelectFourMany<E, F, G, H, TOP> {
250        SelectFourMany {
251            query: self.query,
252            entity: self.entity,
253        }
254    }
255}
256
257impl<E, F, G, H, TOP> SelectFourMany<E, F, G, H, TOP>
258where
259    E: EntityTrait,
260    F: EntityTrait,
261    G: EntityTrait,
262    H: EntityTrait,
263    TOP: Topology,
264{
265    /// Performs a conversion to [Selector]
266    fn into_model<M, N, O, P>(self) -> Selector<SelectFourModel<M, N, O, P>>
267    where
268        M: FromQueryResult,
269        N: FromQueryResult,
270        O: FromQueryResult,
271        P: FromQueryResult,
272    {
273        Selector {
274            query: self.query,
275            selector: PhantomData,
276        }
277    }
278}
279
280impl<E, F, G, H> SelectFourMany<E, F, G, H, TopologyStar>
281where
282    E: EntityTrait,
283    F: EntityTrait,
284    G: EntityTrait,
285    H: EntityTrait,
286{
287    /// Execute query and consolidate rows by E
288    pub async fn all<C>(
289        self,
290        db: &C,
291    ) -> Result<Vec<(E::Model, Vec<F::Model>, Vec<G::Model>, Vec<H::Model>)>, DbErr>
292    where
293        C: ConnectionTrait,
294    {
295        let rows = self.into_model().all(db).await?;
296        Ok(consolidate_query_result_quad_star::<E, F, G, H>(rows))
297    }
298}
299
300impl<'db, C, EE, FF, GG, HH, E, F, G, H, TOP> PaginatorTrait<'db, C> for SelectFour<E, F, G, H, TOP>
301where
302    C: ConnectionTrait,
303    E: EntityTrait<Model = EE>,
304    F: EntityTrait<Model = FF>,
305    G: EntityTrait<Model = GG>,
306    H: EntityTrait<Model = HH>,
307    EE: FromQueryResult + Sized + Send + Sync + 'db,
308    FF: FromQueryResult + Sized + Send + Sync + 'db,
309    GG: FromQueryResult + Sized + Send + Sync + 'db,
310    HH: FromQueryResult + Sized + Send + Sync + 'db,
311    TOP: Topology,
312{
313    type Selector = SelectFourModel<EE, FF, GG, HH>;
314
315    fn paginate(self, db: &'db C, page_size: u64) -> Paginator<'db, C, Self::Selector> {
316        self.into_model().paginate(db, page_size)
317    }
318}