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