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