Skip to main content

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