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 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)
173    }
174
175    /// Get all Models from the Select query
176    pub 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)
192    }
193
194    /// Stream the results of a Select operation on a Model
195    #[cfg(feature = "stream")]
196    pub fn stream<'a: 'b, 'b, C>(
197        self,
198        db: &'a C,
199    ) -> Result<
200        impl Iterator<
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,
215    {
216        self.into_model().stream(db)
217    }
218
219    /// Stream the result of the operation with PartialModel
220    #[cfg(feature = "stream")]
221    pub fn stream_partial_model<'a: 'b, 'b, C, M, N, O, P>(
222        self,
223        db: &'a C,
224    ) -> Result<impl Iterator<Item = Result<(M, Option<N>, Option<O>, Option<P>), DbErr>> + 'b, DbErr>
225    where
226        C: ConnectionTrait + StreamTrait,
227        M: PartialModelTrait + 'b,
228        N: PartialModelTrait + 'b,
229        O: PartialModelTrait + 'b,
230        P: PartialModelTrait + 'b,
231    {
232        self.into_partial_model().stream(db)
233    }
234}
235
236impl<E, F, G, H, TOP> SelectFour<E, F, G, H, TOP>
237where
238    E: EntityTrait,
239    F: EntityTrait,
240    G: EntityTrait,
241    H: EntityTrait,
242    TOP: Topology,
243{
244    /// Consolidate query result by first model. Only the star topology
245    /// (E -> F, E -> G, E -> H) provides an `all()` impl.
246    pub fn consolidate(self) -> SelectFourMany<E, F, G, H, TOP> {
247        SelectFourMany {
248            query: self.query,
249            entity: self.entity,
250        }
251    }
252}
253
254impl<E, F, G, H, TOP> SelectFourMany<E, F, G, H, TOP>
255where
256    E: EntityTrait,
257    F: EntityTrait,
258    G: EntityTrait,
259    H: EntityTrait,
260    TOP: Topology,
261{
262    /// Performs a conversion to [Selector]
263    fn into_model<M, N, O, P>(self) -> Selector<SelectFourModel<M, N, O, P>>
264    where
265        M: FromQueryResult,
266        N: FromQueryResult,
267        O: FromQueryResult,
268        P: FromQueryResult,
269    {
270        Selector {
271            query: self.query,
272            selector: PhantomData,
273        }
274    }
275}
276
277impl<E, F, G, H> SelectFourMany<E, F, G, H, TopologyStar>
278where
279    E: EntityTrait,
280    F: EntityTrait,
281    G: EntityTrait,
282    H: EntityTrait,
283{
284    /// Execute query and consolidate rows by E
285    pub fn all<C>(
286        self,
287        db: &C,
288    ) -> Result<Vec<(E::Model, Vec<F::Model>, Vec<G::Model>, Vec<H::Model>)>, DbErr>
289    where
290        C: ConnectionTrait,
291    {
292        let rows = self.into_model().all(db)?;
293        Ok(consolidate_query_result_quad_star::<E, F, G, H>(rows))
294    }
295}
296
297impl<'db, C, EE, FF, GG, HH, E, F, G, H, TOP> PaginatorTrait<'db, C> for SelectFour<E, F, G, H, TOP>
298where
299    C: ConnectionTrait,
300    E: EntityTrait<Model = EE>,
301    F: EntityTrait<Model = FF>,
302    G: EntityTrait<Model = GG>,
303    H: EntityTrait<Model = HH>,
304    EE: FromQueryResult + Sized + 'db,
305    FF: FromQueryResult + Sized + 'db,
306    GG: FromQueryResult + Sized + 'db,
307    HH: FromQueryResult + Sized + 'db,
308    TOP: Topology,
309{
310    type Selector = SelectFourModel<EE, FF, GG, HH>;
311
312    fn paginate(self, db: &'db C, page_size: u64) -> Paginator<'db, C, Self::Selector> {
313        self.into_model().paginate(db, page_size)
314    }
315}