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