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 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)
154 }
155
156 pub 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)
165 }
166
167 pub fn stream<'a: 'b, 'b, C>(
169 self,
170 db: &'a C,
171 ) -> Result<
172 impl Iterator<Item = Result<(E::Model, Option<F::Model>, Option<G::Model>), DbErr>> + 'b,
173 DbErr,
174 >
175 where
176 C: ConnectionTrait + StreamTrait,
177 {
178 self.into_model().stream(db)
179 }
180
181 pub fn stream_partial_model<'a: 'b, 'b, C, M, N, O>(
183 self,
184 db: &'a C,
185 ) -> Result<impl Iterator<Item = Result<(M, Option<N>, Option<O>), DbErr>> + 'b, DbErr>
186 where
187 C: ConnectionTrait + StreamTrait,
188 M: PartialModelTrait + 'b,
189 N: PartialModelTrait + 'b,
190 O: PartialModelTrait + 'b,
191 {
192 self.into_partial_model().stream(db)
193 }
194
195 pub fn consolidate(self) -> SelectThreeMany<E, F, G, TOP> {
219 SelectThreeMany {
220 query: self.query,
221 entity: self.entity,
222 }
223 }
224}
225
226impl<E, F, G, TOP> SelectThreeMany<E, F, G, TOP>
227where
228 E: EntityTrait,
229 F: EntityTrait,
230 G: EntityTrait,
231 TOP: Topology,
232{
233 fn into_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
235 where
236 M: FromQueryResult,
237 N: FromQueryResult,
238 O: FromQueryResult,
239 {
240 Selector {
241 query: self.query,
242 selector: PhantomData,
243 }
244 }
245}
246
247impl<E, F, G> SelectThreeMany<E, F, G, TopologyStar>
248where
249 E: EntityTrait,
250 F: EntityTrait,
251 G: EntityTrait,
252{
253 pub fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Vec<F::Model>, Vec<G::Model>)>, DbErr>
255 where
256 C: ConnectionTrait,
257 {
258 let rows = self.into_model().all(db)?;
259 Ok(consolidate_query_result_tee::<E, F, G>(rows))
260 }
261}
262
263impl<E, F, G> SelectThreeMany<E, F, G, TopologyChain>
264where
265 E: EntityTrait,
266 F: EntityTrait,
267 G: EntityTrait,
268{
269 pub fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Vec<(F::Model, Vec<G::Model>)>)>, DbErr>
271 where
272 C: ConnectionTrait,
273 {
274 let rows = self.into_model().all(db)?;
275 Ok(consolidate_query_result_chain::<E, F, G>(rows))
276 }
277}
278
279impl<'db, C, M, N, O, E, F, G, TOP> PaginatorTrait<'db, C> for SelectThree<E, F, G, TOP>
280where
281 C: ConnectionTrait,
282 E: EntityTrait<Model = M>,
283 F: EntityTrait<Model = N>,
284 G: EntityTrait<Model = O>,
285 M: FromQueryResult + Sized + 'db,
286 N: FromQueryResult + Sized + 'db,
287 O: FromQueryResult + Sized + 'db,
288 TOP: Topology,
289{
290 type Selector = SelectThreeModel<M, N, O>;
291
292 fn paginate(self, db: &'db C, page_size: u64) -> Paginator<'db, C, Self::Selector> {
293 self.into_model().paginate(db, page_size)
294 }
295}