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