sea_orm/executor/
select.rs

1use super::{
2    consolidate_query_result, consolidate_query_result_chain, consolidate_query_result_tee,
3};
4use crate::{
5    ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, IdenStatic, PartialModelTrait,
6    QueryResult, QuerySelect, Select, SelectA, SelectB, SelectC, SelectThree, SelectThreeMany,
7    SelectTwo, SelectTwoMany, Statement, StreamTrait, Topology, TopologyChain, TopologyStar,
8    TryGetableMany, error::*,
9};
10use futures_util::{Stream, TryStreamExt};
11use sea_query::SelectStatement;
12use std::{marker::PhantomData, pin::Pin};
13
14#[cfg(feature = "with-json")]
15use crate::JsonValue;
16
17/// Defines a type to do `SELECT` operations through a [SelectStatement] on a Model
18#[derive(Clone, Debug)]
19pub struct Selector<S>
20where
21    S: SelectorTrait,
22{
23    pub(crate) query: SelectStatement,
24    selector: PhantomData<S>,
25}
26
27/// Performs a raw `SELECT` operation on a model
28#[derive(Clone, Debug)]
29pub struct SelectorRaw<S>
30where
31    S: SelectorTrait,
32{
33    pub(crate) stmt: Statement,
34    pub(super) selector: PhantomData<S>,
35}
36
37/// A Trait for any type that can perform SELECT queries
38pub trait SelectorTrait {
39    #[allow(missing_docs)]
40    type Item: Sized;
41
42    /// The method to perform a query on a Model
43    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr>;
44}
45
46/// Get tuple from query result based on a list of column identifiers
47#[derive(Debug)]
48pub struct SelectGetableValue<T, C>
49where
50    T: TryGetableMany,
51    C: strum::IntoEnumIterator + sea_query::Iden,
52{
53    columns: PhantomData<C>,
54    model: PhantomData<T>,
55}
56
57/// Get tuple from query result based on column index
58#[derive(Debug)]
59pub struct SelectGetableTuple<T>
60where
61    T: TryGetableMany,
62{
63    model: PhantomData<T>,
64}
65
66/// Helper class to handle query result for 1 Model
67#[derive(Debug)]
68pub struct SelectModel<M>
69where
70    M: FromQueryResult,
71{
72    model: PhantomData<M>,
73}
74
75/// Helper class to handle query result for 2 Models
76#[derive(Clone, Debug)]
77pub struct SelectTwoModel<M, N>
78where
79    M: FromQueryResult,
80    N: FromQueryResult,
81{
82    model: PhantomData<(M, N)>,
83}
84
85/// Helper class to handle query result for 3 Models
86#[derive(Clone, Debug)]
87pub struct SelectThreeModel<M, N, O>
88where
89    M: FromQueryResult,
90    N: FromQueryResult,
91    O: FromQueryResult,
92{
93    model: PhantomData<(M, N, O)>,
94}
95
96impl<T, C> Default for SelectGetableValue<T, C>
97where
98    T: TryGetableMany,
99    C: strum::IntoEnumIterator + sea_query::Iden,
100{
101    fn default() -> Self {
102        Self {
103            columns: PhantomData,
104            model: PhantomData,
105        }
106    }
107}
108
109impl<T, C> SelectorTrait for SelectGetableValue<T, C>
110where
111    T: TryGetableMany,
112    C: strum::IntoEnumIterator + sea_query::Iden,
113{
114    type Item = T;
115
116    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
117        let cols: Vec<String> = C::iter().map(|col| col.to_string()).collect();
118        T::try_get_many(&res, "", &cols).map_err(Into::into)
119    }
120}
121
122impl<T> SelectorTrait for SelectGetableTuple<T>
123where
124    T: TryGetableMany,
125{
126    type Item = T;
127
128    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
129        T::try_get_many_by_index(&res).map_err(Into::into)
130    }
131}
132
133impl<M> SelectorTrait for SelectModel<M>
134where
135    M: FromQueryResult + Sized,
136{
137    type Item = M;
138
139    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
140        M::from_query_result(&res, "")
141    }
142}
143
144impl<M, N> SelectorTrait for SelectTwoModel<M, N>
145where
146    M: FromQueryResult + Sized,
147    N: FromQueryResult + Sized,
148{
149    type Item = (M, Option<N>);
150
151    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
152        Ok((
153            M::from_query_result(&res, SelectA.as_str())?,
154            N::from_query_result_optional(&res, SelectB.as_str())?,
155        ))
156    }
157}
158
159impl<M, N, O> SelectorTrait for SelectThreeModel<M, N, O>
160where
161    M: FromQueryResult + Sized,
162    N: FromQueryResult + Sized,
163    O: FromQueryResult + Sized,
164{
165    type Item = (M, Option<N>, Option<O>);
166
167    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
168        Ok((
169            M::from_query_result(&res, SelectA.as_str())?,
170            N::from_query_result_optional(&res, SelectB.as_str())?,
171            O::from_query_result_optional(&res, SelectC.as_str())?,
172        ))
173    }
174}
175
176impl<E> Select<E>
177where
178    E: EntityTrait,
179{
180    /// Perform a Select operation on a Model using a [Statement]
181    #[allow(clippy::wrong_self_convention)]
182    pub fn from_raw_sql(self, stmt: Statement) -> SelectorRaw<SelectModel<E::Model>> {
183        SelectorRaw {
184            stmt,
185            selector: PhantomData,
186        }
187    }
188
189    /// Return a [Selector] from `Self` that wraps a [SelectModel]
190    pub fn into_model<M>(self) -> Selector<SelectModel<M>>
191    where
192        M: FromQueryResult,
193    {
194        Selector {
195            query: self.query,
196            selector: PhantomData,
197        }
198    }
199
200    /// Return a [Selector] from `Self` that wraps a [SelectModel] with a [PartialModel](PartialModelTrait)
201    ///
202    /// ```
203    /// # #[cfg(feature = "macros")]
204    /// # {
205    /// use sea_orm::{
206    ///     entity::*,
207    ///     query::*,
208    ///     tests_cfg::cake::{self, Entity as Cake},
209    ///     DbBackend, DerivePartialModel,
210    /// };
211    /// use sea_query::{Expr, Func, SimpleExpr};
212    ///
213    /// #[derive(DerivePartialModel)]
214    /// #[sea_orm(entity = "Cake")]
215    /// struct PartialCake {
216    ///     name: String,
217    ///     #[sea_orm(
218    ///         from_expr = r#"SimpleExpr::FunctionCall(Func::upper(Expr::col((Cake, cake::Column::Name))))"#
219    ///     )]
220    ///     name_upper: String,
221    /// }
222    ///
223    /// assert_eq!(
224    ///     cake::Entity::find()
225    ///         .into_partial_model::<PartialCake>()
226    ///         .into_statement(DbBackend::Sqlite)
227    ///         .to_string(),
228    ///     r#"SELECT "cake"."name" AS "name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
229    /// );
230    /// # }
231    /// ```
232    pub fn into_partial_model<M>(self) -> Selector<SelectModel<M>>
233    where
234        M: PartialModelTrait,
235    {
236        M::select_cols(QuerySelect::select_only(self)).into_model::<M>()
237    }
238
239    /// Get a selectable Model as a [JsonValue] for SQL JSON operations
240    #[cfg(feature = "with-json")]
241    pub fn into_json(self) -> Selector<SelectModel<JsonValue>> {
242        Selector {
243            query: self.query,
244            selector: PhantomData,
245        }
246    }
247
248    /// ```
249    /// # use sea_orm::{error::*, tests_cfg::*, *};
250    /// #
251    /// # #[smol_potat::main]
252    /// # #[cfg(all(feature = "mock", feature = "macros"))]
253    /// # pub async fn main() -> Result<(), DbErr> {
254    /// #
255    /// # let db = MockDatabase::new(DbBackend::Postgres)
256    /// #     .append_query_results([[
257    /// #         maplit::btreemap! {
258    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
259    /// #         },
260    /// #         maplit::btreemap! {
261    /// #             "cake_name" => Into::<Value>::into("New York Cheese"),
262    /// #         },
263    /// #     ]])
264    /// #     .into_connection();
265    /// #
266    /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
267    ///
268    /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
269    /// enum QueryAs {
270    ///     CakeName,
271    /// }
272    ///
273    /// let res: Vec<String> = cake::Entity::find()
274    ///     .select_only()
275    ///     .column_as(cake::Column::Name, QueryAs::CakeName)
276    ///     .into_values::<_, QueryAs>()
277    ///     .all(&db)
278    ///     .await?;
279    ///
280    /// assert_eq!(
281    ///     res,
282    ///     ["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
283    /// );
284    ///
285    /// assert_eq!(
286    ///     db.into_transaction_log(),
287    ///     [Transaction::from_sql_and_values(
288    ///         DbBackend::Postgres,
289    ///         r#"SELECT "cake"."name" AS "cake_name" FROM "cake""#,
290    ///         []
291    ///     )]
292    /// );
293    /// #
294    /// # Ok(())
295    /// # }
296    /// ```
297    ///
298    /// ```
299    /// # use sea_orm::{error::*, tests_cfg::*, *};
300    /// #
301    /// # #[smol_potat::main]
302    /// # #[cfg(all(feature = "mock", feature = "macros"))]
303    /// # pub async fn main() -> Result<(), DbErr> {
304    /// #
305    /// # let db = MockDatabase::new(DbBackend::Postgres)
306    /// #     .append_query_results([[
307    /// #         maplit::btreemap! {
308    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
309    /// #             "num_of_cakes" => Into::<Value>::into(2i64),
310    /// #         },
311    /// #     ]])
312    /// #     .into_connection();
313    /// #
314    /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
315    ///
316    /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
317    /// enum QueryAs {
318    ///     CakeName,
319    ///     NumOfCakes,
320    /// }
321    ///
322    /// let res: Vec<(String, i64)> = cake::Entity::find()
323    ///     .select_only()
324    ///     .column_as(cake::Column::Name, QueryAs::CakeName)
325    ///     .column_as(cake::Column::Id.count(), QueryAs::NumOfCakes)
326    ///     .group_by(cake::Column::Name)
327    ///     .into_values::<_, QueryAs>()
328    ///     .all(&db)
329    ///     .await?;
330    ///
331    /// assert_eq!(res, [("Chocolate Forest".to_owned(), 2i64)]);
332    ///
333    /// assert_eq!(
334    ///     db.into_transaction_log(),
335    ///     [Transaction::from_sql_and_values(
336    ///         DbBackend::Postgres,
337    ///         [
338    ///             r#"SELECT "cake"."name" AS "cake_name", COUNT("cake"."id") AS "num_of_cakes""#,
339    ///             r#"FROM "cake" GROUP BY "cake"."name""#,
340    ///         ]
341    ///         .join(" ")
342    ///         .as_str(),
343    ///         []
344    ///     )]
345    /// );
346    /// #
347    /// # Ok(())
348    /// # }
349    /// ```
350    pub fn into_values<T, C>(self) -> Selector<SelectGetableValue<T, C>>
351    where
352        T: TryGetableMany,
353        C: strum::IntoEnumIterator + sea_query::Iden,
354    {
355        Selector {
356            query: self.query,
357            selector: PhantomData,
358        }
359    }
360
361    /// ```
362    /// # use sea_orm::{error::*, tests_cfg::*, *};
363    /// #
364    /// # #[smol_potat::main]
365    /// # #[cfg(all(feature = "mock", feature = "macros"))]
366    /// # pub async fn main() -> Result<(), DbErr> {
367    /// #
368    /// # let db = MockDatabase::new(DbBackend::Postgres)
369    /// #     .append_query_results(vec![vec![
370    /// #         maplit::btreemap! {
371    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
372    /// #         },
373    /// #         maplit::btreemap! {
374    /// #             "cake_name" => Into::<Value>::into("New York Cheese"),
375    /// #         },
376    /// #     ]])
377    /// #     .into_connection();
378    /// #
379    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
380    ///
381    /// let res: Vec<String> = cake::Entity::find()
382    ///     .select_only()
383    ///     .column(cake::Column::Name)
384    ///     .into_tuple()
385    ///     .all(&db)
386    ///     .await?;
387    ///
388    /// assert_eq!(
389    ///     res,
390    ///     vec!["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
391    /// );
392    ///
393    /// assert_eq!(
394    ///     db.into_transaction_log(),
395    ///     vec![Transaction::from_sql_and_values(
396    ///         DbBackend::Postgres,
397    ///         r#"SELECT "cake"."name" FROM "cake""#,
398    ///         vec![]
399    ///     )]
400    /// );
401    /// #
402    /// # Ok(())
403    /// # }
404    /// ```
405    ///
406    /// ```
407    /// # use sea_orm::{error::*, tests_cfg::*, *};
408    /// #
409    /// # #[smol_potat::main]
410    /// # #[cfg(all(feature = "mock", feature = "macros"))]
411    /// # pub async fn main() -> Result<(), DbErr> {
412    /// #
413    /// # let db = MockDatabase::new(DbBackend::Postgres)
414    /// #     .append_query_results(vec![vec![
415    /// #         maplit::btreemap! {
416    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
417    /// #             "num_of_cakes" => Into::<Value>::into(2i64),
418    /// #         },
419    /// #     ]])
420    /// #     .into_connection();
421    /// #
422    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
423    ///
424    /// let res: Vec<(String, i64)> = cake::Entity::find()
425    ///     .select_only()
426    ///     .column(cake::Column::Name)
427    ///     .column(cake::Column::Id)
428    ///     .group_by(cake::Column::Name)
429    ///     .into_tuple()
430    ///     .all(&db)
431    ///     .await?;
432    ///
433    /// assert_eq!(res, vec![("Chocolate Forest".to_owned(), 2i64)]);
434    ///
435    /// assert_eq!(
436    ///     db.into_transaction_log(),
437    ///     vec![Transaction::from_sql_and_values(
438    ///         DbBackend::Postgres,
439    ///         vec![
440    ///             r#"SELECT "cake"."name", "cake"."id""#,
441    ///             r#"FROM "cake" GROUP BY "cake"."name""#,
442    ///         ]
443    ///         .join(" ")
444    ///         .as_str(),
445    ///         vec![]
446    ///     )]
447    /// );
448    /// #
449    /// # Ok(())
450    /// # }
451    /// ```
452    pub fn into_tuple<T>(self) -> Selector<SelectGetableTuple<T>>
453    where
454        T: TryGetableMany,
455    {
456        Selector {
457            query: self.query,
458            selector: PhantomData,
459        }
460    }
461
462    /// Get one Model from the SELECT query
463    pub async fn one<C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
464    where
465        C: ConnectionTrait,
466    {
467        self.into_model().one(db).await
468    }
469
470    /// Get all Models from the SELECT query
471    pub async fn all<C>(self, db: &C) -> Result<Vec<E::Model>, DbErr>
472    where
473        C: ConnectionTrait,
474    {
475        self.into_model().all(db).await
476    }
477
478    /// Stream the results of a SELECT operation on a Model
479    pub async fn stream<'a: 'b, 'b, C>(
480        self,
481        db: &'a C,
482    ) -> Result<impl Stream<Item = Result<E::Model, DbErr>> + 'b + Send, DbErr>
483    where
484        C: ConnectionTrait + StreamTrait + Send,
485    {
486        self.into_model().stream(db).await
487    }
488
489    /// Stream the result of the operation with PartialModel
490    pub async fn stream_partial_model<'a: 'b, 'b, C, M>(
491        self,
492        db: &'a C,
493    ) -> Result<impl Stream<Item = Result<M, DbErr>> + 'b + Send, DbErr>
494    where
495        C: ConnectionTrait + StreamTrait + Send,
496        M: PartialModelTrait + Send + 'b,
497    {
498        self.into_partial_model().stream(db).await
499    }
500}
501
502impl<E, F> SelectTwo<E, F>
503where
504    E: EntityTrait,
505    F: EntityTrait,
506{
507    /// Perform a conversion into a [SelectTwoModel]
508    pub fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
509    where
510        M: FromQueryResult,
511        N: FromQueryResult,
512    {
513        Selector {
514            query: self.query,
515            selector: PhantomData,
516        }
517    }
518
519    /// Perform a conversion into a [SelectTwoModel] with [PartialModel](PartialModelTrait)
520    pub fn into_partial_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
521    where
522        M: PartialModelTrait,
523        N: PartialModelTrait,
524    {
525        let select = QuerySelect::select_only(self);
526        let select = M::select_cols(select);
527        let select = N::select_cols(select);
528        select.into_model::<M, N>()
529    }
530
531    /// Convert the Models into JsonValue
532    #[cfg(feature = "with-json")]
533    pub fn into_json(self) -> Selector<SelectTwoModel<JsonValue, JsonValue>> {
534        Selector {
535            query: self.query,
536            selector: PhantomData,
537        }
538    }
539
540    /// Get one Model from the Select query
541    pub async fn one<C>(self, db: &C) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr>
542    where
543        C: ConnectionTrait,
544    {
545        self.into_model().one(db).await
546    }
547
548    /// Get all Models from the Select query
549    pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr>
550    where
551        C: ConnectionTrait,
552    {
553        self.into_model().all(db).await
554    }
555
556    /// Stream the results of a Select operation on a Model
557    pub async fn stream<'a: 'b, 'b, C>(
558        self,
559        db: &'a C,
560    ) -> Result<impl Stream<Item = Result<(E::Model, Option<F::Model>), DbErr>> + 'b, DbErr>
561    where
562        C: ConnectionTrait + StreamTrait + Send,
563    {
564        self.into_model().stream(db).await
565    }
566
567    /// Stream the result of the operation with PartialModel
568    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N>(
569        self,
570        db: &'a C,
571    ) -> Result<impl Stream<Item = Result<(M, Option<N>), DbErr>> + 'b + Send, DbErr>
572    where
573        C: ConnectionTrait + StreamTrait + Send,
574        M: PartialModelTrait + Send + 'b,
575        N: PartialModelTrait + Send + 'b,
576    {
577        self.into_partial_model().stream(db).await
578    }
579}
580
581impl<E, F> SelectTwoMany<E, F>
582where
583    E: EntityTrait,
584    F: EntityTrait,
585{
586    /// Performs a conversion to [Selector]
587    fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
588    where
589        M: FromQueryResult,
590        N: FromQueryResult,
591    {
592        Selector {
593            query: self.query,
594            selector: PhantomData,
595        }
596    }
597
598    /// Get all Models from the select operation and consolidate result based on left Model.
599    ///
600    /// > `SelectTwoMany::one()` method has been dropped (#486)
601    /// >
602    /// > You can get `(Entity, Vec<relatedEntity>)` by first querying a single model from Entity,
603    /// > then use [`ModelTrait::find_related`] on the model.
604    /// >
605    /// > See https://www.sea-ql.org/SeaORM/docs/basic-crud/select#lazy-loading for details.
606    pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr>
607    where
608        C: ConnectionTrait,
609    {
610        let rows = self.into_model().all(db).await?;
611        Ok(consolidate_query_result::<E, F>(rows))
612    }
613
614    // pub fn paginate()
615    // we could not implement paginate easily, if the number of children for a
616    // parent is larger than one page, then we will end up splitting it in two pages
617    // so the correct way is actually perform query in two stages
618    // paginate the parent model and then populate the children
619
620    // pub fn count()
621    // we should only count the number of items of the parent model
622}
623
624impl<E, F, G, TOP> SelectThree<E, F, G, TOP>
625where
626    E: EntityTrait,
627    F: EntityTrait,
628    G: EntityTrait,
629    TOP: Topology,
630{
631    /// Perform a conversion into a [SelectThreeModel]
632    pub fn into_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
633    where
634        M: FromQueryResult,
635        N: FromQueryResult,
636        O: FromQueryResult,
637    {
638        Selector {
639            query: self.query,
640            selector: PhantomData,
641        }
642    }
643
644    /// Perform a conversion into a [SelectThreeModel] with [PartialModel](PartialModelTrait)
645    pub fn into_partial_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
646    where
647        M: PartialModelTrait,
648        N: PartialModelTrait,
649        O: PartialModelTrait,
650    {
651        let select = QuerySelect::select_only(self);
652        let select = M::select_cols(select);
653        let select = N::select_cols(select);
654        select.into_model::<M, N, O>()
655    }
656
657    /// Convert the Models into JsonValue
658    #[cfg(feature = "with-json")]
659    pub fn into_json(self) -> Selector<SelectThreeModel<JsonValue, JsonValue, JsonValue>> {
660        Selector {
661            query: self.query,
662            selector: PhantomData,
663        }
664    }
665
666    /// Get one Model from the Select query
667    pub async fn one<C>(
668        self,
669        db: &C,
670    ) -> Result<Option<(E::Model, Option<F::Model>, Option<G::Model>)>, DbErr>
671    where
672        C: ConnectionTrait,
673    {
674        self.into_model().one(db).await
675    }
676
677    /// Get all Models from the Select query
678    pub async fn all<C>(
679        self,
680        db: &C,
681    ) -> Result<Vec<(E::Model, Option<F::Model>, Option<G::Model>)>, DbErr>
682    where
683        C: ConnectionTrait,
684    {
685        self.into_model().all(db).await
686    }
687
688    /// Stream the results of a Select operation on a Model
689    pub async fn stream<'a: 'b, 'b, C>(
690        self,
691        db: &'a C,
692    ) -> Result<
693        impl Stream<Item = Result<(E::Model, Option<F::Model>, Option<G::Model>), DbErr>> + 'b,
694        DbErr,
695    >
696    where
697        C: ConnectionTrait + StreamTrait + Send,
698    {
699        self.into_model().stream(db).await
700    }
701
702    /// Stream the result of the operation with PartialModel
703    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N, O>(
704        self,
705        db: &'a C,
706    ) -> Result<impl Stream<Item = Result<(M, Option<N>, Option<O>), DbErr>> + 'b + Send, DbErr>
707    where
708        C: ConnectionTrait + StreamTrait + Send,
709        M: PartialModelTrait + Send + 'b,
710        N: PartialModelTrait + Send + 'b,
711        O: PartialModelTrait + Send + 'b,
712    {
713        self.into_partial_model().stream(db).await
714    }
715
716    /// Consolidate query result by first / second model depending on join topology
717    /// ```
718    /// # use sea_orm::{tests_cfg::*, *};
719    /// # async fn function(db: &DbConn) -> Result<(), DbErr> {
720    /// // fruit -> cake -> filling
721    /// let items: Vec<(fruit::Model, Vec<(cake::Model, Vec<filling::Model>)>)> = fruit::Entity::find()
722    ///     .find_also_related(cake::Entity)
723    ///     .and_also_related(filling::Entity)
724    ///     .consolidate()
725    ///     .all(db)
726    ///     .await?;
727    ///
728    /// // cake -> fruit
729    /// //      -> filling
730    /// let items: Vec<(cake::Model, Vec<fruit::Model>, Vec<filling::Model>)> = cake::Entity::find()
731    ///     .find_also_related(fruit::Entity)
732    ///     .find_also_related(filling::Entity)
733    ///     .consolidate()
734    ///     .all(db)
735    ///     .await?;
736    /// # Ok(())
737    /// # }
738    /// ```
739    pub fn consolidate(self) -> SelectThreeMany<E, F, G, TOP> {
740        SelectThreeMany {
741            query: self.query,
742            entity: self.entity,
743        }
744    }
745}
746
747impl<E, F, G, TOP> SelectThreeMany<E, F, G, TOP>
748where
749    E: EntityTrait,
750    F: EntityTrait,
751    G: EntityTrait,
752    TOP: Topology,
753{
754    /// Performs a conversion to [Selector]
755    fn into_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
756    where
757        M: FromQueryResult,
758        N: FromQueryResult,
759        O: FromQueryResult,
760    {
761        Selector {
762            query: self.query,
763            selector: PhantomData,
764        }
765    }
766}
767
768impl<E, F, G> SelectThreeMany<E, F, G, TopologyStar>
769where
770    E: EntityTrait,
771    F: EntityTrait,
772    G: EntityTrait,
773{
774    /// Execute query and consolidate rows by E
775    pub async fn all<C>(
776        self,
777        db: &C,
778    ) -> Result<Vec<(E::Model, Vec<F::Model>, Vec<G::Model>)>, DbErr>
779    where
780        C: ConnectionTrait,
781    {
782        let rows = self.into_model().all(db).await?;
783        Ok(consolidate_query_result_tee::<E, F, G>(rows))
784    }
785}
786
787impl<E, F, G> SelectThreeMany<E, F, G, TopologyChain>
788where
789    E: EntityTrait,
790    F: EntityTrait,
791    G: EntityTrait,
792{
793    /// Execute query and consolidate rows in two passes, first by E, then by F
794    pub async fn all<C>(
795        self,
796        db: &C,
797    ) -> Result<Vec<(E::Model, Vec<(F::Model, Vec<G::Model>)>)>, DbErr>
798    where
799        C: ConnectionTrait,
800    {
801        let rows = self.into_model().all(db).await?;
802        Ok(consolidate_query_result_chain::<E, F, G>(rows))
803    }
804}
805
806impl<S> Selector<S>
807where
808    S: SelectorTrait,
809{
810    /// Get the SQL statement
811    pub fn into_statement(self, builder: DbBackend) -> Statement {
812        builder.build(&self.query)
813    }
814
815    /// Get an item from the Select query
816    pub async fn one<C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
817    where
818        C: ConnectionTrait,
819    {
820        self.query.limit(1);
821        let row = db.query_one(&self.query).await?;
822        match row {
823            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
824            None => Ok(None),
825        }
826    }
827
828    /// Get all items from the Select query
829    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
830    where
831        C: ConnectionTrait,
832    {
833        let rows = db.query_all(&self.query).await?;
834        let mut models = Vec::new();
835        for row in rows.into_iter() {
836            models.push(S::from_raw_query_result(row)?);
837        }
838        Ok(models)
839    }
840
841    /// Stream the results of the Select operation
842    pub async fn stream<'a: 'b, 'b, C>(
843        self,
844        db: &'a C,
845    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
846    where
847        C: ConnectionTrait + StreamTrait + Send,
848        S: 'b,
849        S::Item: Send,
850    {
851        let stream = db.stream(&self.query).await?;
852        Ok(Box::pin(stream.and_then(|row| {
853            futures_util::future::ready(S::from_raw_query_result(row))
854        })))
855    }
856}
857
858impl<S> SelectorRaw<S>
859where
860    S: SelectorTrait,
861{
862    /// Select a custom Model from a raw SQL [Statement].
863    pub fn from_statement<M>(stmt: Statement) -> SelectorRaw<SelectModel<M>>
864    where
865        M: FromQueryResult,
866    {
867        SelectorRaw {
868            stmt,
869            selector: PhantomData,
870        }
871    }
872
873    /// ```
874    /// # use sea_orm::{error::*, tests_cfg::*, *};
875    /// #
876    /// # #[smol_potat::main]
877    /// # #[cfg(feature = "mock")]
878    /// # pub async fn main() -> Result<(), DbErr> {
879    /// #
880    /// # let db = MockDatabase::new(DbBackend::Postgres)
881    /// #     .append_query_results([[
882    /// #         maplit::btreemap! {
883    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
884    /// #             "num_of_cakes" => Into::<Value>::into(1),
885    /// #         },
886    /// #         maplit::btreemap! {
887    /// #             "name" => Into::<Value>::into("New York Cheese"),
888    /// #             "num_of_cakes" => Into::<Value>::into(1),
889    /// #         },
890    /// #     ]])
891    /// #     .into_connection();
892    /// #
893    /// use sea_orm::{FromQueryResult, entity::*, query::*, tests_cfg::cake};
894    ///
895    /// #[derive(Debug, PartialEq, FromQueryResult)]
896    /// struct SelectResult {
897    ///     name: String,
898    ///     num_of_cakes: i32,
899    /// }
900    ///
901    /// let res: Vec<SelectResult> = cake::Entity::find()
902    ///     .from_raw_sql(Statement::from_sql_and_values(
903    ///         DbBackend::Postgres,
904    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
905    ///         [],
906    ///     ))
907    ///     .into_model::<SelectResult>()
908    ///     .all(&db)
909    ///     .await?;
910    ///
911    /// assert_eq!(
912    ///     res,
913    ///     [
914    ///         SelectResult {
915    ///             name: "Chocolate Forest".to_owned(),
916    ///             num_of_cakes: 1,
917    ///         },
918    ///         SelectResult {
919    ///             name: "New York Cheese".to_owned(),
920    ///             num_of_cakes: 1,
921    ///         },
922    ///     ]
923    /// );
924    ///
925    /// assert_eq!(
926    ///     db.into_transaction_log(),
927    ///     [Transaction::from_sql_and_values(
928    ///         DbBackend::Postgres,
929    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
930    ///         []
931    ///     ),]
932    /// );
933    /// #
934    /// # Ok(())
935    /// # }
936    /// ```
937    pub fn into_model<M>(self) -> SelectorRaw<SelectModel<M>>
938    where
939        M: FromQueryResult,
940    {
941        SelectorRaw {
942            stmt: self.stmt,
943            selector: PhantomData,
944        }
945    }
946
947    /// ```
948    /// # use sea_orm::{error::*, tests_cfg::*, *};
949    /// #
950    /// # #[smol_potat::main]
951    /// # #[cfg(feature = "mock")]
952    /// # pub async fn main() -> Result<(), DbErr> {
953    /// #
954    /// # let db = MockDatabase::new(DbBackend::Postgres)
955    /// #     .append_query_results([[
956    /// #         maplit::btreemap! {
957    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
958    /// #             "num_of_cakes" => Into::<Value>::into(1),
959    /// #         },
960    /// #         maplit::btreemap! {
961    /// #             "name" => Into::<Value>::into("New York Cheese"),
962    /// #             "num_of_cakes" => Into::<Value>::into(1),
963    /// #         },
964    /// #     ]])
965    /// #     .into_connection();
966    /// #
967    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
968    ///
969    /// let res: Vec<serde_json::Value> = cake::Entity::find().from_raw_sql(
970    ///     Statement::from_sql_and_values(
971    ///         DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
972    ///     )
973    /// )
974    /// .into_json()
975    /// .all(&db)
976    /// .await?;
977    ///
978    /// assert_eq!(
979    ///     res,
980    ///     [
981    ///         serde_json::json!({
982    ///             "name": "Chocolate Forest",
983    ///             "num_of_cakes": 1,
984    ///         }),
985    ///         serde_json::json!({
986    ///             "name": "New York Cheese",
987    ///             "num_of_cakes": 1,
988    ///         }),
989    ///     ]
990    /// );
991    ///
992    /// assert_eq!(
993    ///     db.into_transaction_log(),
994    ///     [
995    ///     Transaction::from_sql_and_values(
996    ///             DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
997    ///     ),
998    /// ]);
999    /// #
1000    /// # Ok(())
1001    /// # }
1002    /// ```
1003    #[cfg(feature = "with-json")]
1004    pub fn into_json(self) -> SelectorRaw<SelectModel<JsonValue>> {
1005        SelectorRaw {
1006            stmt: self.stmt,
1007            selector: PhantomData,
1008        }
1009    }
1010
1011    /// Get the SQL statement
1012    pub fn into_statement(self) -> Statement {
1013        self.stmt
1014    }
1015
1016    /// Get an item from the Select query
1017    /// ```
1018    /// # use sea_orm::{error::*, tests_cfg::*, *};
1019    /// #
1020    /// # #[smol_potat::main]
1021    /// # #[cfg(feature = "mock")]
1022    /// # pub async fn main() -> Result<(), DbErr> {
1023    /// #
1024    /// # let db = MockDatabase::new(DbBackend::Postgres)
1025    /// #     .append_query_results([
1026    /// #         [cake::Model {
1027    /// #             id: 1,
1028    /// #             name: "Cake".to_owned(),
1029    /// #         }],
1030    /// #     ])
1031    /// #     .into_connection();
1032    /// #
1033    /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
1034    ///
1035    /// let id = 1;
1036    ///
1037    /// let _: Option<cake::Model> = cake::Entity::find()
1038    ///     .from_raw_sql(raw_sql!(
1039    ///         Postgres,
1040    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = {id}"#
1041    ///     ))
1042    ///     .one(&db)
1043    ///     .await?;
1044    ///
1045    /// assert_eq!(
1046    ///     db.into_transaction_log(),
1047    ///     [Transaction::from_sql_and_values(
1048    ///         DbBackend::Postgres,
1049    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = $1"#,
1050    ///         [1.into()]
1051    ///     ),]
1052    /// );
1053    /// #
1054    /// # Ok(())
1055    /// # }
1056    /// ```
1057    pub async fn one<C>(self, db: &C) -> Result<Option<S::Item>, DbErr>
1058    where
1059        C: ConnectionTrait,
1060    {
1061        let row = db.query_one_raw(self.stmt).await?;
1062        match row {
1063            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
1064            None => Ok(None),
1065        }
1066    }
1067
1068    /// Get all items from the Select query
1069    /// ```
1070    /// # use sea_orm::{error::*, tests_cfg::*, *};
1071    /// #
1072    /// # #[smol_potat::main]
1073    /// # #[cfg(feature = "mock")]
1074    /// # pub async fn main() -> Result<(), DbErr> {
1075    /// #
1076    /// # let db = MockDatabase::new(DbBackend::Postgres)
1077    /// #     .append_query_results([
1078    /// #         [cake::Model {
1079    /// #             id: 1,
1080    /// #             name: "Cake".to_owned(),
1081    /// #         }],
1082    /// #     ])
1083    /// #     .into_connection();
1084    /// #
1085    /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
1086    ///
1087    /// let _: Vec<cake::Model> = cake::Entity::find()
1088    ///     .from_raw_sql(raw_sql!(
1089    ///         Postgres,
1090    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#
1091    ///     ))
1092    ///     .all(&db)
1093    ///     .await?;
1094    ///
1095    /// assert_eq!(
1096    ///     db.into_transaction_log(),
1097    ///     [Transaction::from_sql_and_values(
1098    ///         DbBackend::Postgres,
1099    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
1100    ///         []
1101    ///     ),]
1102    /// );
1103    /// #
1104    /// # Ok(())
1105    /// # }
1106    /// ```
1107    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
1108    where
1109        C: ConnectionTrait,
1110    {
1111        let rows = db.query_all_raw(self.stmt).await?;
1112        let mut models = Vec::new();
1113        for row in rows.into_iter() {
1114            models.push(S::from_raw_query_result(row)?);
1115        }
1116        Ok(models)
1117    }
1118
1119    /// Stream the results of the Select operation
1120    pub async fn stream<'a: 'b, 'b, C>(
1121        self,
1122        db: &'a C,
1123    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
1124    where
1125        C: ConnectionTrait + StreamTrait + Send,
1126        S: 'b,
1127        S::Item: Send,
1128    {
1129        let stream = db.stream_raw(self.stmt).await?;
1130        Ok(Box::pin(stream.and_then(|row| {
1131            futures_util::future::ready(S::from_raw_query_result(row))
1132        })))
1133    }
1134}