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