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 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 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 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 #[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 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 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 #[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 #[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 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 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 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}