Skip to main content

sea_orm/executor/
select.rs

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