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