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    pub fn consolidate(self) -> SelectThreeMany<E, F, G, TOP> {
718        SelectThreeMany {
719            query: self.query,
720            entity: self.entity,
721        }
722    }
723}
724
725impl<E, F, G, TOP> SelectThreeMany<E, F, G, TOP>
726where
727    E: EntityTrait,
728    F: EntityTrait,
729    G: EntityTrait,
730    TOP: Topology,
731{
732    /// Performs a conversion to [Selector]
733    fn into_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
734    where
735        M: FromQueryResult,
736        N: FromQueryResult,
737        O: FromQueryResult,
738    {
739        Selector {
740            query: self.query,
741            selector: PhantomData,
742        }
743    }
744}
745
746impl<E, F, G> SelectThreeMany<E, F, G, TopologyStar>
747where
748    E: EntityTrait,
749    F: EntityTrait,
750    G: EntityTrait,
751{
752    /// Execute query and consolidate rows by E
753    pub async fn all<C>(
754        self,
755        db: &C,
756    ) -> Result<Vec<(E::Model, Vec<F::Model>, Vec<G::Model>)>, DbErr>
757    where
758        C: ConnectionTrait,
759    {
760        let rows = self.into_model().all(db).await?;
761        Ok(consolidate_query_result_tee::<E, F, G>(rows))
762    }
763}
764
765impl<E, F, G> SelectThreeMany<E, F, G, TopologyChain>
766where
767    E: EntityTrait,
768    F: EntityTrait,
769    G: EntityTrait,
770{
771    /// Execute query and consolidate rows in two passes, first by E, then by F
772    pub async fn all<C>(
773        self,
774        db: &C,
775    ) -> Result<Vec<(E::Model, Vec<(F::Model, Vec<G::Model>)>)>, DbErr>
776    where
777        C: ConnectionTrait,
778    {
779        let rows = self.into_model().all(db).await?;
780        Ok(consolidate_query_result_chain::<E, F, G>(rows))
781    }
782}
783
784impl<S> Selector<S>
785where
786    S: SelectorTrait,
787{
788    /// Get the SQL statement
789    pub fn into_statement(self, builder: DbBackend) -> Statement {
790        builder.build(&self.query)
791    }
792
793    /// Get an item from the Select query
794    pub async fn one<C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
795    where
796        C: ConnectionTrait,
797    {
798        self.query.limit(1);
799        let row = db.query_one(&self.query).await?;
800        match row {
801            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
802            None => Ok(None),
803        }
804    }
805
806    /// Get all items from the Select query
807    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
808    where
809        C: ConnectionTrait,
810    {
811        let rows = db.query_all(&self.query).await?;
812        let mut models = Vec::new();
813        for row in rows.into_iter() {
814            models.push(S::from_raw_query_result(row)?);
815        }
816        Ok(models)
817    }
818
819    /// Stream the results of the Select operation
820    pub async fn stream<'a: 'b, 'b, C>(
821        self,
822        db: &'a C,
823    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
824    where
825        C: ConnectionTrait + StreamTrait + Send,
826        S: 'b,
827        S::Item: Send,
828    {
829        let stream = db.stream(&self.query).await?;
830        Ok(Box::pin(stream.and_then(|row| {
831            futures_util::future::ready(S::from_raw_query_result(row))
832        })))
833    }
834}
835
836impl<S> SelectorRaw<S>
837where
838    S: SelectorTrait,
839{
840    /// Select a custom Model from a raw SQL [Statement].
841    pub fn from_statement<M>(stmt: Statement) -> SelectorRaw<SelectModel<M>>
842    where
843        M: FromQueryResult,
844    {
845        SelectorRaw {
846            stmt,
847            selector: PhantomData,
848        }
849    }
850
851    /// ```
852    /// # use sea_orm::{error::*, tests_cfg::*, *};
853    /// #
854    /// # #[smol_potat::main]
855    /// # #[cfg(feature = "mock")]
856    /// # pub async fn main() -> Result<(), DbErr> {
857    /// #
858    /// # let db = MockDatabase::new(DbBackend::Postgres)
859    /// #     .append_query_results([[
860    /// #         maplit::btreemap! {
861    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
862    /// #             "num_of_cakes" => Into::<Value>::into(1),
863    /// #         },
864    /// #         maplit::btreemap! {
865    /// #             "name" => Into::<Value>::into("New York Cheese"),
866    /// #             "num_of_cakes" => Into::<Value>::into(1),
867    /// #         },
868    /// #     ]])
869    /// #     .into_connection();
870    /// #
871    /// use sea_orm::{FromQueryResult, entity::*, query::*, tests_cfg::cake};
872    ///
873    /// #[derive(Debug, PartialEq, FromQueryResult)]
874    /// struct SelectResult {
875    ///     name: String,
876    ///     num_of_cakes: i32,
877    /// }
878    ///
879    /// let res: Vec<SelectResult> = cake::Entity::find()
880    ///     .from_raw_sql(Statement::from_sql_and_values(
881    ///         DbBackend::Postgres,
882    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
883    ///         [],
884    ///     ))
885    ///     .into_model::<SelectResult>()
886    ///     .all(&db)
887    ///     .await?;
888    ///
889    /// assert_eq!(
890    ///     res,
891    ///     [
892    ///         SelectResult {
893    ///             name: "Chocolate Forest".to_owned(),
894    ///             num_of_cakes: 1,
895    ///         },
896    ///         SelectResult {
897    ///             name: "New York Cheese".to_owned(),
898    ///             num_of_cakes: 1,
899    ///         },
900    ///     ]
901    /// );
902    ///
903    /// assert_eq!(
904    ///     db.into_transaction_log(),
905    ///     [Transaction::from_sql_and_values(
906    ///         DbBackend::Postgres,
907    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
908    ///         []
909    ///     ),]
910    /// );
911    /// #
912    /// # Ok(())
913    /// # }
914    /// ```
915    pub fn into_model<M>(self) -> SelectorRaw<SelectModel<M>>
916    where
917        M: FromQueryResult,
918    {
919        SelectorRaw {
920            stmt: self.stmt,
921            selector: PhantomData,
922        }
923    }
924
925    /// ```
926    /// # use sea_orm::{error::*, tests_cfg::*, *};
927    /// #
928    /// # #[smol_potat::main]
929    /// # #[cfg(feature = "mock")]
930    /// # pub async fn main() -> Result<(), DbErr> {
931    /// #
932    /// # let db = MockDatabase::new(DbBackend::Postgres)
933    /// #     .append_query_results([[
934    /// #         maplit::btreemap! {
935    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
936    /// #             "num_of_cakes" => Into::<Value>::into(1),
937    /// #         },
938    /// #         maplit::btreemap! {
939    /// #             "name" => Into::<Value>::into("New York Cheese"),
940    /// #             "num_of_cakes" => Into::<Value>::into(1),
941    /// #         },
942    /// #     ]])
943    /// #     .into_connection();
944    /// #
945    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
946    ///
947    /// let res: Vec<serde_json::Value> = cake::Entity::find().from_raw_sql(
948    ///     Statement::from_sql_and_values(
949    ///         DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
950    ///     )
951    /// )
952    /// .into_json()
953    /// .all(&db)
954    /// .await?;
955    ///
956    /// assert_eq!(
957    ///     res,
958    ///     [
959    ///         serde_json::json!({
960    ///             "name": "Chocolate Forest",
961    ///             "num_of_cakes": 1,
962    ///         }),
963    ///         serde_json::json!({
964    ///             "name": "New York Cheese",
965    ///             "num_of_cakes": 1,
966    ///         }),
967    ///     ]
968    /// );
969    ///
970    /// assert_eq!(
971    ///     db.into_transaction_log(),
972    ///     [
973    ///     Transaction::from_sql_and_values(
974    ///             DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
975    ///     ),
976    /// ]);
977    /// #
978    /// # Ok(())
979    /// # }
980    /// ```
981    #[cfg(feature = "with-json")]
982    pub fn into_json(self) -> SelectorRaw<SelectModel<JsonValue>> {
983        SelectorRaw {
984            stmt: self.stmt,
985            selector: PhantomData,
986        }
987    }
988
989    /// Get the SQL statement
990    pub fn into_statement(self) -> Statement {
991        self.stmt
992    }
993
994    /// Get an item from the Select query
995    /// ```
996    /// # use sea_orm::{error::*, tests_cfg::*, *};
997    /// #
998    /// # #[smol_potat::main]
999    /// # #[cfg(feature = "mock")]
1000    /// # pub async fn main() -> Result<(), DbErr> {
1001    /// #
1002    /// # let db = MockDatabase::new(DbBackend::Postgres)
1003    /// #     .append_query_results([
1004    /// #         [cake::Model {
1005    /// #             id: 1,
1006    /// #             name: "Cake".to_owned(),
1007    /// #         }],
1008    /// #     ])
1009    /// #     .into_connection();
1010    /// #
1011    /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
1012    ///
1013    /// let id = 1;
1014    ///
1015    /// let _: Option<cake::Model> = cake::Entity::find()
1016    ///     .from_raw_sql(raw_sql!(
1017    ///         Postgres,
1018    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = {id}"#
1019    ///     ))
1020    ///     .one(&db)
1021    ///     .await?;
1022    ///
1023    /// assert_eq!(
1024    ///     db.into_transaction_log(),
1025    ///     [Transaction::from_sql_and_values(
1026    ///         DbBackend::Postgres,
1027    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = $1"#,
1028    ///         [1.into()]
1029    ///     ),]
1030    /// );
1031    /// #
1032    /// # Ok(())
1033    /// # }
1034    /// ```
1035    pub async fn one<C>(self, db: &C) -> Result<Option<S::Item>, DbErr>
1036    where
1037        C: ConnectionTrait,
1038    {
1039        let row = db.query_one_raw(self.stmt).await?;
1040        match row {
1041            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
1042            None => Ok(None),
1043        }
1044    }
1045
1046    /// Get all items from the Select query
1047    /// ```
1048    /// # use sea_orm::{error::*, tests_cfg::*, *};
1049    /// #
1050    /// # #[smol_potat::main]
1051    /// # #[cfg(feature = "mock")]
1052    /// # pub async fn main() -> Result<(), DbErr> {
1053    /// #
1054    /// # let db = MockDatabase::new(DbBackend::Postgres)
1055    /// #     .append_query_results([
1056    /// #         [cake::Model {
1057    /// #             id: 1,
1058    /// #             name: "Cake".to_owned(),
1059    /// #         }],
1060    /// #     ])
1061    /// #     .into_connection();
1062    /// #
1063    /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
1064    ///
1065    /// let _: Vec<cake::Model> = cake::Entity::find()
1066    ///     .from_raw_sql(raw_sql!(
1067    ///         Postgres,
1068    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#
1069    ///     ))
1070    ///     .all(&db)
1071    ///     .await?;
1072    ///
1073    /// assert_eq!(
1074    ///     db.into_transaction_log(),
1075    ///     [Transaction::from_sql_and_values(
1076    ///         DbBackend::Postgres,
1077    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
1078    ///         []
1079    ///     ),]
1080    /// );
1081    /// #
1082    /// # Ok(())
1083    /// # }
1084    /// ```
1085    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
1086    where
1087        C: ConnectionTrait,
1088    {
1089        let rows = db.query_all_raw(self.stmt).await?;
1090        let mut models = Vec::new();
1091        for row in rows.into_iter() {
1092            models.push(S::from_raw_query_result(row)?);
1093        }
1094        Ok(models)
1095    }
1096
1097    /// Stream the results of the Select operation
1098    pub async fn stream<'a: 'b, 'b, C>(
1099        self,
1100        db: &'a C,
1101    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
1102    where
1103        C: ConnectionTrait + StreamTrait + Send,
1104        S: 'b,
1105        S::Item: Send,
1106    {
1107        let stream = db.stream_raw(self.stmt).await?;
1108        Ok(Box::pin(stream.and_then(|row| {
1109            futures_util::future::ready(S::from_raw_query_result(row))
1110        })))
1111    }
1112}