sea_orm/executor/
select.rs

1use crate::{
2    ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, IdenStatic, Iterable, ModelTrait,
3    PartialModelTrait, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait, QueryResult,
4    QuerySelect, Select, SelectA, SelectB, SelectC, SelectThree, SelectTwo, SelectTwoMany,
5    Statement, StreamTrait, TryGetableMany, error::*,
6};
7use futures_util::{Stream, TryStreamExt};
8use sea_query::{SelectStatement, Value};
9use std::collections::HashMap;
10use std::{hash::Hash, marker::PhantomData, pin::Pin};
11
12#[cfg(feature = "with-json")]
13use crate::JsonValue;
14
15/// Defines a type to do `SELECT` operations through a [SelectStatement] on a Model
16#[derive(Clone, Debug)]
17pub struct Selector<S>
18where
19    S: SelectorTrait,
20{
21    pub(crate) query: SelectStatement,
22    selector: PhantomData<S>,
23}
24
25/// Performs a raw `SELECT` operation on a model
26#[derive(Clone, Debug)]
27pub struct SelectorRaw<S>
28where
29    S: SelectorTrait,
30{
31    pub(crate) stmt: Statement,
32    pub(super) selector: PhantomData<S>,
33}
34
35/// A Trait for any type that can perform SELECT queries
36pub trait SelectorTrait {
37    #[allow(missing_docs)]
38    type Item: Sized;
39
40    /// The method to perform a query on a Model
41    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr>;
42}
43
44/// Get tuple from query result based on a list of column identifiers
45#[derive(Debug)]
46pub struct SelectGetableValue<T, C>
47where
48    T: TryGetableMany,
49    C: strum::IntoEnumIterator + sea_query::Iden,
50{
51    columns: PhantomData<C>,
52    model: PhantomData<T>,
53}
54
55/// Get tuple from query result based on column index
56#[derive(Debug)]
57pub struct SelectGetableTuple<T>
58where
59    T: TryGetableMany,
60{
61    model: PhantomData<T>,
62}
63
64/// Helper class to handle query result for 1 Model
65#[derive(Debug)]
66pub struct SelectModel<M>
67where
68    M: FromQueryResult,
69{
70    model: PhantomData<M>,
71}
72
73/// Helper class to handle query result for 2 Models
74#[derive(Clone, Debug)]
75pub struct SelectTwoModel<M, N>
76where
77    M: FromQueryResult,
78    N: FromQueryResult,
79{
80    model: PhantomData<(M, N)>,
81}
82
83/// Helper class to handle query result for 3 Models
84#[derive(Clone, Debug)]
85pub struct SelectThreeModel<M, N, O>
86where
87    M: FromQueryResult,
88    N: FromQueryResult,
89    O: FromQueryResult,
90{
91    model: PhantomData<(M, N, O)>,
92}
93
94impl<T, C> Default for SelectGetableValue<T, C>
95where
96    T: TryGetableMany,
97    C: strum::IntoEnumIterator + sea_query::Iden,
98{
99    fn default() -> Self {
100        Self {
101            columns: PhantomData,
102            model: PhantomData,
103        }
104    }
105}
106
107impl<T, C> SelectorTrait for SelectGetableValue<T, C>
108where
109    T: TryGetableMany,
110    C: strum::IntoEnumIterator + sea_query::Iden,
111{
112    type Item = T;
113
114    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
115        let cols: Vec<String> = C::iter().map(|col| col.to_string()).collect();
116        T::try_get_many(&res, "", &cols).map_err(Into::into)
117    }
118}
119
120impl<T> SelectorTrait for SelectGetableTuple<T>
121where
122    T: TryGetableMany,
123{
124    type Item = T;
125
126    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
127        T::try_get_many_by_index(&res).map_err(Into::into)
128    }
129}
130
131impl<M> SelectorTrait for SelectModel<M>
132where
133    M: FromQueryResult + Sized,
134{
135    type Item = M;
136
137    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
138        M::from_query_result(&res, "")
139    }
140}
141
142impl<M, N> SelectorTrait for SelectTwoModel<M, N>
143where
144    M: FromQueryResult + Sized,
145    N: FromQueryResult + Sized,
146{
147    type Item = (M, Option<N>);
148
149    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
150        Ok((
151            M::from_query_result(&res, SelectA.as_str())?,
152            N::from_query_result_optional(&res, SelectB.as_str())?,
153        ))
154    }
155}
156
157impl<M, N, O> SelectorTrait for SelectThreeModel<M, N, O>
158where
159    M: FromQueryResult + Sized,
160    N: FromQueryResult + Sized,
161    O: FromQueryResult + Sized,
162{
163    type Item = (M, Option<N>, Option<O>);
164
165    fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
166        Ok((
167            M::from_query_result(&res, SelectA.as_str())?,
168            N::from_query_result_optional(&res, SelectB.as_str())?,
169            O::from_query_result_optional(&res, SelectC.as_str())?,
170        ))
171    }
172}
173
174impl<E> Select<E>
175where
176    E: EntityTrait,
177{
178    /// Perform a Select operation on a Model using a [Statement]
179    #[allow(clippy::wrong_self_convention)]
180    pub fn from_raw_sql(self, stmt: Statement) -> SelectorRaw<SelectModel<E::Model>> {
181        SelectorRaw {
182            stmt,
183            selector: PhantomData,
184        }
185    }
186
187    /// Return a [Selector] from `Self` that wraps a [SelectModel]
188    pub fn into_model<M>(self) -> Selector<SelectModel<M>>
189    where
190        M: FromQueryResult,
191    {
192        Selector {
193            query: self.query,
194            selector: PhantomData,
195        }
196    }
197
198    /// Return a [Selector] from `Self` that wraps a [SelectModel] with a [PartialModel](PartialModelTrait)
199    ///
200    /// ```
201    /// # #[cfg(feature = "macros")]
202    /// # {
203    /// use sea_orm::{
204    ///     entity::*,
205    ///     query::*,
206    ///     tests_cfg::cake::{self, Entity as Cake},
207    ///     DbBackend, DerivePartialModel,
208    /// };
209    /// use sea_query::{Expr, Func, SimpleExpr};
210    ///
211    /// #[derive(DerivePartialModel)]
212    /// #[sea_orm(entity = "Cake")]
213    /// struct PartialCake {
214    ///     name: String,
215    ///     #[sea_orm(
216    ///         from_expr = r#"SimpleExpr::FunctionCall(Func::upper(Expr::col((Cake, cake::Column::Name))))"#
217    ///     )]
218    ///     name_upper: String,
219    /// }
220    ///
221    /// assert_eq!(
222    ///     cake::Entity::find()
223    ///         .into_partial_model::<PartialCake>()
224    ///         .into_statement(DbBackend::Sqlite)
225    ///         .to_string(),
226    ///     r#"SELECT "cake"."name" AS "name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
227    /// );
228    /// # }
229    /// ```
230    pub fn into_partial_model<M>(self) -> Selector<SelectModel<M>>
231    where
232        M: PartialModelTrait,
233    {
234        M::select_cols(QuerySelect::select_only(self)).into_model::<M>()
235    }
236
237    /// Get a selectable Model as a [JsonValue] for SQL JSON operations
238    #[cfg(feature = "with-json")]
239    pub fn into_json(self) -> Selector<SelectModel<JsonValue>> {
240        Selector {
241            query: self.query,
242            selector: PhantomData,
243        }
244    }
245
246    /// ```
247    /// # use sea_orm::{error::*, tests_cfg::*, *};
248    /// #
249    /// # #[smol_potat::main]
250    /// # #[cfg(all(feature = "mock", feature = "macros"))]
251    /// # pub async fn main() -> Result<(), DbErr> {
252    /// #
253    /// # let db = MockDatabase::new(DbBackend::Postgres)
254    /// #     .append_query_results([[
255    /// #         maplit::btreemap! {
256    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
257    /// #         },
258    /// #         maplit::btreemap! {
259    /// #             "cake_name" => Into::<Value>::into("New York Cheese"),
260    /// #         },
261    /// #     ]])
262    /// #     .into_connection();
263    /// #
264    /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
265    ///
266    /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
267    /// enum QueryAs {
268    ///     CakeName,
269    /// }
270    ///
271    /// let res: Vec<String> = cake::Entity::find()
272    ///     .select_only()
273    ///     .column_as(cake::Column::Name, QueryAs::CakeName)
274    ///     .into_values::<_, QueryAs>()
275    ///     .all(&db)
276    ///     .await?;
277    ///
278    /// assert_eq!(
279    ///     res,
280    ///     ["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
281    /// );
282    ///
283    /// assert_eq!(
284    ///     db.into_transaction_log(),
285    ///     [Transaction::from_sql_and_values(
286    ///         DbBackend::Postgres,
287    ///         r#"SELECT "cake"."name" AS "cake_name" FROM "cake""#,
288    ///         []
289    ///     )]
290    /// );
291    /// #
292    /// # Ok(())
293    /// # }
294    /// ```
295    ///
296    /// ```
297    /// # use sea_orm::{error::*, tests_cfg::*, *};
298    /// #
299    /// # #[smol_potat::main]
300    /// # #[cfg(all(feature = "mock", feature = "macros"))]
301    /// # pub async fn main() -> Result<(), DbErr> {
302    /// #
303    /// # let db = MockDatabase::new(DbBackend::Postgres)
304    /// #     .append_query_results([[
305    /// #         maplit::btreemap! {
306    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
307    /// #             "num_of_cakes" => Into::<Value>::into(2i64),
308    /// #         },
309    /// #     ]])
310    /// #     .into_connection();
311    /// #
312    /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
313    ///
314    /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
315    /// enum QueryAs {
316    ///     CakeName,
317    ///     NumOfCakes,
318    /// }
319    ///
320    /// let res: Vec<(String, i64)> = cake::Entity::find()
321    ///     .select_only()
322    ///     .column_as(cake::Column::Name, QueryAs::CakeName)
323    ///     .column_as(cake::Column::Id.count(), QueryAs::NumOfCakes)
324    ///     .group_by(cake::Column::Name)
325    ///     .into_values::<_, QueryAs>()
326    ///     .all(&db)
327    ///     .await?;
328    ///
329    /// assert_eq!(res, [("Chocolate Forest".to_owned(), 2i64)]);
330    ///
331    /// assert_eq!(
332    ///     db.into_transaction_log(),
333    ///     [Transaction::from_sql_and_values(
334    ///         DbBackend::Postgres,
335    ///         [
336    ///             r#"SELECT "cake"."name" AS "cake_name", COUNT("cake"."id") AS "num_of_cakes""#,
337    ///             r#"FROM "cake" GROUP BY "cake"."name""#,
338    ///         ]
339    ///         .join(" ")
340    ///         .as_str(),
341    ///         []
342    ///     )]
343    /// );
344    /// #
345    /// # Ok(())
346    /// # }
347    /// ```
348    pub fn into_values<T, C>(self) -> Selector<SelectGetableValue<T, C>>
349    where
350        T: TryGetableMany,
351        C: strum::IntoEnumIterator + sea_query::Iden,
352    {
353        Selector {
354            query: self.query,
355            selector: PhantomData,
356        }
357    }
358
359    /// ```
360    /// # use sea_orm::{error::*, tests_cfg::*, *};
361    /// #
362    /// # #[smol_potat::main]
363    /// # #[cfg(all(feature = "mock", feature = "macros"))]
364    /// # pub async fn main() -> Result<(), DbErr> {
365    /// #
366    /// # let db = MockDatabase::new(DbBackend::Postgres)
367    /// #     .append_query_results(vec![vec![
368    /// #         maplit::btreemap! {
369    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
370    /// #         },
371    /// #         maplit::btreemap! {
372    /// #             "cake_name" => Into::<Value>::into("New York Cheese"),
373    /// #         },
374    /// #     ]])
375    /// #     .into_connection();
376    /// #
377    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
378    ///
379    /// let res: Vec<String> = cake::Entity::find()
380    ///     .select_only()
381    ///     .column(cake::Column::Name)
382    ///     .into_tuple()
383    ///     .all(&db)
384    ///     .await?;
385    ///
386    /// assert_eq!(
387    ///     res,
388    ///     vec!["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
389    /// );
390    ///
391    /// assert_eq!(
392    ///     db.into_transaction_log(),
393    ///     vec![Transaction::from_sql_and_values(
394    ///         DbBackend::Postgres,
395    ///         r#"SELECT "cake"."name" FROM "cake""#,
396    ///         vec![]
397    ///     )]
398    /// );
399    /// #
400    /// # Ok(())
401    /// # }
402    /// ```
403    ///
404    /// ```
405    /// # use sea_orm::{error::*, tests_cfg::*, *};
406    /// #
407    /// # #[smol_potat::main]
408    /// # #[cfg(all(feature = "mock", feature = "macros"))]
409    /// # pub async fn main() -> Result<(), DbErr> {
410    /// #
411    /// # let db = MockDatabase::new(DbBackend::Postgres)
412    /// #     .append_query_results(vec![vec![
413    /// #         maplit::btreemap! {
414    /// #             "cake_name" => Into::<Value>::into("Chocolate Forest"),
415    /// #             "num_of_cakes" => Into::<Value>::into(2i64),
416    /// #         },
417    /// #     ]])
418    /// #     .into_connection();
419    /// #
420    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
421    ///
422    /// let res: Vec<(String, i64)> = cake::Entity::find()
423    ///     .select_only()
424    ///     .column(cake::Column::Name)
425    ///     .column(cake::Column::Id)
426    ///     .group_by(cake::Column::Name)
427    ///     .into_tuple()
428    ///     .all(&db)
429    ///     .await?;
430    ///
431    /// assert_eq!(res, vec![("Chocolate Forest".to_owned(), 2i64)]);
432    ///
433    /// assert_eq!(
434    ///     db.into_transaction_log(),
435    ///     vec![Transaction::from_sql_and_values(
436    ///         DbBackend::Postgres,
437    ///         vec![
438    ///             r#"SELECT "cake"."name", "cake"."id""#,
439    ///             r#"FROM "cake" GROUP BY "cake"."name""#,
440    ///         ]
441    ///         .join(" ")
442    ///         .as_str(),
443    ///         vec![]
444    ///     )]
445    /// );
446    /// #
447    /// # Ok(())
448    /// # }
449    /// ```
450    pub fn into_tuple<T>(self) -> Selector<SelectGetableTuple<T>>
451    where
452        T: TryGetableMany,
453    {
454        Selector {
455            query: self.query,
456            selector: PhantomData,
457        }
458    }
459
460    /// Get one Model from the SELECT query
461    pub async fn one<C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
462    where
463        C: ConnectionTrait,
464    {
465        self.into_model().one(db).await
466    }
467
468    /// Get all Models from the SELECT query
469    pub async fn all<C>(self, db: &C) -> Result<Vec<E::Model>, DbErr>
470    where
471        C: ConnectionTrait,
472    {
473        self.into_model().all(db).await
474    }
475
476    /// Stream the results of a SELECT operation on a Model
477    pub async fn stream<'a: 'b, 'b, C>(
478        self,
479        db: &'a C,
480    ) -> Result<impl Stream<Item = Result<E::Model, DbErr>> + 'b + Send, DbErr>
481    where
482        C: ConnectionTrait + StreamTrait + Send,
483    {
484        self.into_model().stream(db).await
485    }
486
487    /// Stream the result of the operation with PartialModel
488    pub async fn stream_partial_model<'a: 'b, 'b, C, M>(
489        self,
490        db: &'a C,
491    ) -> Result<impl Stream<Item = Result<M, DbErr>> + 'b + Send, DbErr>
492    where
493        C: ConnectionTrait + StreamTrait + Send,
494        M: PartialModelTrait + Send + 'b,
495    {
496        self.into_partial_model().stream(db).await
497    }
498}
499
500impl<E, F> SelectTwo<E, F>
501where
502    E: EntityTrait,
503    F: EntityTrait,
504{
505    /// Perform a conversion into a [SelectTwoModel]
506    pub fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
507    where
508        M: FromQueryResult,
509        N: FromQueryResult,
510    {
511        Selector {
512            query: self.query,
513            selector: PhantomData,
514        }
515    }
516
517    /// Perform a conversion into a [SelectTwoModel] with [PartialModel](PartialModelTrait)
518    pub fn into_partial_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
519    where
520        M: PartialModelTrait,
521        N: PartialModelTrait,
522    {
523        let select = QuerySelect::select_only(self);
524        let select = M::select_cols(select);
525        let select = N::select_cols(select);
526        select.into_model::<M, N>()
527    }
528
529    /// Convert the Models into JsonValue
530    #[cfg(feature = "with-json")]
531    pub fn into_json(self) -> Selector<SelectTwoModel<JsonValue, JsonValue>> {
532        Selector {
533            query: self.query,
534            selector: PhantomData,
535        }
536    }
537
538    /// Get one Model from the Select query
539    pub async fn one<C>(self, db: &C) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr>
540    where
541        C: ConnectionTrait,
542    {
543        self.into_model().one(db).await
544    }
545
546    /// Get all Models from the Select query
547    pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr>
548    where
549        C: ConnectionTrait,
550    {
551        self.into_model().all(db).await
552    }
553
554    /// Stream the results of a Select operation on a Model
555    pub async fn stream<'a: 'b, 'b, C>(
556        self,
557        db: &'a C,
558    ) -> Result<impl Stream<Item = Result<(E::Model, Option<F::Model>), DbErr>> + 'b, DbErr>
559    where
560        C: ConnectionTrait + StreamTrait + Send,
561    {
562        self.into_model().stream(db).await
563    }
564
565    /// Stream the result of the operation with PartialModel
566    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N>(
567        self,
568        db: &'a C,
569    ) -> Result<impl Stream<Item = Result<(M, Option<N>), DbErr>> + 'b + Send, DbErr>
570    where
571        C: ConnectionTrait + StreamTrait + Send,
572        M: PartialModelTrait + Send + 'b,
573        N: PartialModelTrait + Send + 'b,
574    {
575        self.into_partial_model().stream(db).await
576    }
577}
578
579impl<E, F> SelectTwoMany<E, F>
580where
581    E: EntityTrait,
582    F: EntityTrait,
583{
584    /// Performs a conversion to [Selector]
585    fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
586    where
587        M: FromQueryResult,
588        N: FromQueryResult,
589    {
590        Selector {
591            query: self.query,
592            selector: PhantomData,
593        }
594    }
595
596    /// Performs a conversion to [Selector] with partial model
597    fn into_partial_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
598    where
599        M: PartialModelTrait,
600        N: PartialModelTrait,
601    {
602        let select = self.select_only();
603        let select = M::select_cols(select);
604        let select = N::select_cols(select);
605        select.into_model()
606    }
607
608    /// Convert the results to JSON
609    #[cfg(feature = "with-json")]
610    pub fn into_json(self) -> Selector<SelectTwoModel<JsonValue, JsonValue>> {
611        Selector {
612            query: self.query,
613            selector: PhantomData,
614        }
615    }
616
617    /// Stream the result of the operation
618    pub async fn stream<'a: 'b, 'b, C>(
619        self,
620        db: &'a C,
621    ) -> Result<impl Stream<Item = Result<(E::Model, Option<F::Model>), DbErr>> + 'b + Send, DbErr>
622    where
623        C: ConnectionTrait + StreamTrait + Send,
624    {
625        self.into_model().stream(db).await
626    }
627
628    /// Stream the result of the operation with PartialModel
629    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N>(
630        self,
631        db: &'a C,
632    ) -> Result<impl Stream<Item = Result<(M, Option<N>), DbErr>> + 'b + Send, DbErr>
633    where
634        C: ConnectionTrait + StreamTrait + Send,
635        M: PartialModelTrait + Send + 'b,
636        N: PartialModelTrait + Send + 'b,
637    {
638        self.into_partial_model().stream(db).await
639    }
640
641    /// Get all Models from the select operation
642    ///
643    /// > `SelectTwoMany::one()` method has been dropped (#486)
644    /// >
645    /// > You can get `(Entity, Vec<relatedEntity>)` by first querying a single model from Entity,
646    /// > then use [`ModelTrait::find_related`] on the model.
647    /// >
648    /// > See https://www.sea-ql.org/SeaORM/docs/basic-crud/select#lazy-loading for details.
649    pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr>
650    where
651        C: ConnectionTrait,
652    {
653        let rows = self.into_model().all(db).await?;
654        Ok(consolidate_query_result::<E, F>(rows))
655    }
656
657    // pub fn paginate()
658    // we could not implement paginate easily, if the number of children for a
659    // parent is larger than one page, then we will end up splitting it in two pages
660    // so the correct way is actually perform query in two stages
661    // paginate the parent model and then populate the children
662
663    // pub fn count()
664    // we should only count the number of items of the parent model
665}
666
667impl<E, F, G> SelectThree<E, F, G>
668where
669    E: EntityTrait,
670    F: EntityTrait,
671    G: EntityTrait,
672{
673    /// Perform a conversion into a [SelectThreeModel]
674    pub fn into_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
675    where
676        M: FromQueryResult,
677        N: FromQueryResult,
678        O: FromQueryResult,
679    {
680        Selector {
681            query: self.query,
682            selector: PhantomData,
683        }
684    }
685
686    /// Perform a conversion into a [SelectThreeModel] with [PartialModel](PartialModelTrait)
687    pub fn into_partial_model<M, N, O>(self) -> Selector<SelectThreeModel<M, N, O>>
688    where
689        M: PartialModelTrait,
690        N: PartialModelTrait,
691        O: PartialModelTrait,
692    {
693        let select = QuerySelect::select_only(self);
694        let select = M::select_cols(select);
695        let select = N::select_cols(select);
696        select.into_model::<M, N, O>()
697    }
698
699    /// Convert the Models into JsonValue
700    #[cfg(feature = "with-json")]
701    pub fn into_json(self) -> Selector<SelectThreeModel<JsonValue, JsonValue, JsonValue>> {
702        Selector {
703            query: self.query,
704            selector: PhantomData,
705        }
706    }
707
708    /// Get one Model from the Select query
709    pub async fn one<C>(
710        self,
711        db: &C,
712    ) -> Result<Option<(E::Model, Option<F::Model>, Option<G::Model>)>, DbErr>
713    where
714        C: ConnectionTrait,
715    {
716        self.into_model().one(db).await
717    }
718
719    /// Get all Models from the Select query
720    pub async fn all<C>(
721        self,
722        db: &C,
723    ) -> Result<Vec<(E::Model, Option<F::Model>, Option<G::Model>)>, DbErr>
724    where
725        C: ConnectionTrait,
726    {
727        self.into_model().all(db).await
728    }
729
730    /// Stream the results of a Select operation on a Model
731    pub async fn stream<'a: 'b, 'b, C>(
732        self,
733        db: &'a C,
734    ) -> Result<
735        impl Stream<Item = Result<(E::Model, Option<F::Model>, Option<G::Model>), DbErr>> + 'b,
736        DbErr,
737    >
738    where
739        C: ConnectionTrait + StreamTrait + Send,
740    {
741        self.into_model().stream(db).await
742    }
743
744    /// Stream the result of the operation with PartialModel
745    pub async fn stream_partial_model<'a: 'b, 'b, C, M, N, O>(
746        self,
747        db: &'a C,
748    ) -> Result<impl Stream<Item = Result<(M, Option<N>, Option<O>), DbErr>> + 'b + Send, DbErr>
749    where
750        C: ConnectionTrait + StreamTrait + Send,
751        M: PartialModelTrait + Send + 'b,
752        N: PartialModelTrait + Send + 'b,
753        O: PartialModelTrait + Send + 'b,
754    {
755        self.into_partial_model().stream(db).await
756    }
757}
758
759impl<S> Selector<S>
760where
761    S: SelectorTrait,
762{
763    /// Get the SQL statement
764    pub fn into_statement(self, builder: DbBackend) -> Statement {
765        builder.build(&self.query)
766    }
767
768    /// Get an item from the Select query
769    pub async fn one<C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
770    where
771        C: ConnectionTrait,
772    {
773        self.query.limit(1);
774        let row = db.query_one(&self.query).await?;
775        match row {
776            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
777            None => Ok(None),
778        }
779    }
780
781    /// Get all items from the Select query
782    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
783    where
784        C: ConnectionTrait,
785    {
786        let rows = db.query_all(&self.query).await?;
787        let mut models = Vec::new();
788        for row in rows.into_iter() {
789            models.push(S::from_raw_query_result(row)?);
790        }
791        Ok(models)
792    }
793
794    /// Stream the results of the Select operation
795    pub async fn stream<'a: 'b, 'b, C>(
796        self,
797        db: &'a C,
798    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
799    where
800        C: ConnectionTrait + StreamTrait + Send,
801        S: 'b,
802        S::Item: Send,
803    {
804        let stream = db.stream(&self.query).await?;
805        Ok(Box::pin(stream.and_then(|row| {
806            futures_util::future::ready(S::from_raw_query_result(row))
807        })))
808    }
809}
810
811impl<S> SelectorRaw<S>
812where
813    S: SelectorTrait,
814{
815    /// Select a custom Model from a raw SQL [Statement].
816    pub fn from_statement<M>(stmt: Statement) -> SelectorRaw<SelectModel<M>>
817    where
818        M: FromQueryResult,
819    {
820        SelectorRaw {
821            stmt,
822            selector: PhantomData,
823        }
824    }
825
826    /// ```
827    /// # use sea_orm::{error::*, tests_cfg::*, *};
828    /// #
829    /// # #[smol_potat::main]
830    /// # #[cfg(feature = "mock")]
831    /// # pub async fn main() -> Result<(), DbErr> {
832    /// #
833    /// # let db = MockDatabase::new(DbBackend::Postgres)
834    /// #     .append_query_results([[
835    /// #         maplit::btreemap! {
836    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
837    /// #             "num_of_cakes" => Into::<Value>::into(1),
838    /// #         },
839    /// #         maplit::btreemap! {
840    /// #             "name" => Into::<Value>::into("New York Cheese"),
841    /// #             "num_of_cakes" => Into::<Value>::into(1),
842    /// #         },
843    /// #     ]])
844    /// #     .into_connection();
845    /// #
846    /// use sea_orm::{FromQueryResult, entity::*, query::*, tests_cfg::cake};
847    ///
848    /// #[derive(Debug, PartialEq, FromQueryResult)]
849    /// struct SelectResult {
850    ///     name: String,
851    ///     num_of_cakes: i32,
852    /// }
853    ///
854    /// let res: Vec<SelectResult> = cake::Entity::find()
855    ///     .from_raw_sql(Statement::from_sql_and_values(
856    ///         DbBackend::Postgres,
857    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
858    ///         [],
859    ///     ))
860    ///     .into_model::<SelectResult>()
861    ///     .all(&db)
862    ///     .await?;
863    ///
864    /// assert_eq!(
865    ///     res,
866    ///     [
867    ///         SelectResult {
868    ///             name: "Chocolate Forest".to_owned(),
869    ///             num_of_cakes: 1,
870    ///         },
871    ///         SelectResult {
872    ///             name: "New York Cheese".to_owned(),
873    ///             num_of_cakes: 1,
874    ///         },
875    ///     ]
876    /// );
877    ///
878    /// assert_eq!(
879    ///     db.into_transaction_log(),
880    ///     [Transaction::from_sql_and_values(
881    ///         DbBackend::Postgres,
882    ///         r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
883    ///         []
884    ///     ),]
885    /// );
886    /// #
887    /// # Ok(())
888    /// # }
889    /// ```
890    pub fn into_model<M>(self) -> SelectorRaw<SelectModel<M>>
891    where
892        M: FromQueryResult,
893    {
894        SelectorRaw {
895            stmt: self.stmt,
896            selector: PhantomData,
897        }
898    }
899
900    /// ```
901    /// # use sea_orm::{error::*, tests_cfg::*, *};
902    /// #
903    /// # #[smol_potat::main]
904    /// # #[cfg(feature = "mock")]
905    /// # pub async fn main() -> Result<(), DbErr> {
906    /// #
907    /// # let db = MockDatabase::new(DbBackend::Postgres)
908    /// #     .append_query_results([[
909    /// #         maplit::btreemap! {
910    /// #             "name" => Into::<Value>::into("Chocolate Forest"),
911    /// #             "num_of_cakes" => Into::<Value>::into(1),
912    /// #         },
913    /// #         maplit::btreemap! {
914    /// #             "name" => Into::<Value>::into("New York Cheese"),
915    /// #             "num_of_cakes" => Into::<Value>::into(1),
916    /// #         },
917    /// #     ]])
918    /// #     .into_connection();
919    /// #
920    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
921    ///
922    /// let res: Vec<serde_json::Value> = cake::Entity::find().from_raw_sql(
923    ///     Statement::from_sql_and_values(
924    ///         DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
925    ///     )
926    /// )
927    /// .into_json()
928    /// .all(&db)
929    /// .await?;
930    ///
931    /// assert_eq!(
932    ///     res,
933    ///     [
934    ///         serde_json::json!({
935    ///             "name": "Chocolate Forest",
936    ///             "num_of_cakes": 1,
937    ///         }),
938    ///         serde_json::json!({
939    ///             "name": "New York Cheese",
940    ///             "num_of_cakes": 1,
941    ///         }),
942    ///     ]
943    /// );
944    ///
945    /// assert_eq!(
946    ///     db.into_transaction_log(),
947    ///     [
948    ///     Transaction::from_sql_and_values(
949    ///             DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
950    ///     ),
951    /// ]);
952    /// #
953    /// # Ok(())
954    /// # }
955    /// ```
956    #[cfg(feature = "with-json")]
957    pub fn into_json(self) -> SelectorRaw<SelectModel<JsonValue>> {
958        SelectorRaw {
959            stmt: self.stmt,
960            selector: PhantomData,
961        }
962    }
963
964    /// Get the SQL statement
965    pub fn into_statement(self) -> Statement {
966        self.stmt
967    }
968
969    /// Get an item from the Select query
970    /// ```
971    /// # use sea_orm::{error::*, tests_cfg::*, *};
972    /// #
973    /// # #[smol_potat::main]
974    /// # #[cfg(feature = "mock")]
975    /// # pub async fn main() -> Result<(), DbErr> {
976    /// #
977    /// # let db = MockDatabase::new(DbBackend::Postgres)
978    /// #     .append_query_results([
979    /// #         [cake::Model {
980    /// #             id: 1,
981    /// #             name: "Cake".to_owned(),
982    /// #         }],
983    /// #     ])
984    /// #     .into_connection();
985    /// #
986    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
987    ///
988    /// let _: Option<cake::Model> = cake::Entity::find()
989    ///     .from_raw_sql(Statement::from_sql_and_values(
990    ///         DbBackend::Postgres,
991    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = $1"#,
992    ///         [1.into()],
993    ///     ))
994    ///     .one(&db)
995    ///     .await?;
996    ///
997    /// assert_eq!(
998    ///     db.into_transaction_log(),
999    ///     [Transaction::from_sql_and_values(
1000    ///         DbBackend::Postgres,
1001    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = $1"#,
1002    ///         [1.into()]
1003    ///     ),]
1004    /// );
1005    /// #
1006    /// # Ok(())
1007    /// # }
1008    /// ```
1009    pub async fn one<C>(self, db: &C) -> Result<Option<S::Item>, DbErr>
1010    where
1011        C: ConnectionTrait,
1012    {
1013        let row = db.query_one_raw(self.stmt).await?;
1014        match row {
1015            Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
1016            None => Ok(None),
1017        }
1018    }
1019
1020    /// Get all items from the Select query
1021    /// ```
1022    /// # use sea_orm::{error::*, tests_cfg::*, *};
1023    /// #
1024    /// # #[smol_potat::main]
1025    /// # #[cfg(feature = "mock")]
1026    /// # pub async fn main() -> Result<(), DbErr> {
1027    /// #
1028    /// # let db = MockDatabase::new(DbBackend::Postgres)
1029    /// #     .append_query_results([
1030    /// #         [cake::Model {
1031    /// #             id: 1,
1032    /// #             name: "Cake".to_owned(),
1033    /// #         }],
1034    /// #     ])
1035    /// #     .into_connection();
1036    /// #
1037    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
1038    ///
1039    /// let _: Vec<cake::Model> = cake::Entity::find()
1040    ///     .from_raw_sql(Statement::from_sql_and_values(
1041    ///         DbBackend::Postgres,
1042    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
1043    ///         [],
1044    ///     ))
1045    ///     .all(&db)
1046    ///     .await?;
1047    ///
1048    /// assert_eq!(
1049    ///     db.into_transaction_log(),
1050    ///     [Transaction::from_sql_and_values(
1051    ///         DbBackend::Postgres,
1052    ///         r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
1053    ///         []
1054    ///     ),]
1055    /// );
1056    /// #
1057    /// # Ok(())
1058    /// # }
1059    /// ```
1060    pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
1061    where
1062        C: ConnectionTrait,
1063    {
1064        let rows = db.query_all_raw(self.stmt).await?;
1065        let mut models = Vec::new();
1066        for row in rows.into_iter() {
1067            models.push(S::from_raw_query_result(row)?);
1068        }
1069        Ok(models)
1070    }
1071
1072    /// Stream the results of the Select operation
1073    pub async fn stream<'a: 'b, 'b, C>(
1074        self,
1075        db: &'a C,
1076    ) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b + Send>>, DbErr>
1077    where
1078        C: ConnectionTrait + StreamTrait + Send,
1079        S: 'b,
1080        S::Item: Send,
1081    {
1082        let stream = db.stream_raw(self.stmt).await?;
1083        Ok(Box::pin(stream.and_then(|row| {
1084            futures_util::future::ready(S::from_raw_query_result(row))
1085        })))
1086    }
1087}
1088
1089#[allow(clippy::unwrap_used)]
1090fn consolidate_query_result<L, R>(
1091    rows: Vec<(L::Model, Option<R::Model>)>,
1092) -> Vec<(L::Model, Vec<R::Model>)>
1093where
1094    L: EntityTrait,
1095    R: EntityTrait,
1096{
1097    match <<L::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
1098        1 => {
1099            let col = <L::PrimaryKey as Iterable>::iter()
1100                .next()
1101                .unwrap()
1102                .into_column();
1103            consolidate_query_result_of::<L, R, UnitPk<L>>(rows, UnitPk(col))
1104        }
1105        2 => {
1106            let mut iter = <L::PrimaryKey as Iterable>::iter();
1107            let col1 = iter.next().unwrap().into_column();
1108            let col2 = iter.next().unwrap().into_column();
1109            consolidate_query_result_of::<L, R, PairPk<L>>(rows, PairPk(col1, col2))
1110        }
1111        _ => {
1112            let cols: Vec<_> = <L::PrimaryKey as Iterable>::iter()
1113                .map(|pk| pk.into_column())
1114                .collect();
1115            consolidate_query_result_of::<L, R, TuplePk<L>>(rows, TuplePk(cols))
1116        }
1117    }
1118}
1119
1120trait ModelKey<E: EntityTrait> {
1121    type Type: Hash + PartialEq + Eq;
1122    fn get(&self, model: &E::Model) -> Self::Type;
1123}
1124
1125// This could have been an array of [E::Column; <E::PrimaryKey as PrimaryKeyTrait>::ARITY], but it still doesn't compile
1126struct UnitPk<E: EntityTrait>(E::Column);
1127struct PairPk<E: EntityTrait>(E::Column, E::Column);
1128struct TuplePk<E: EntityTrait>(Vec<E::Column>);
1129
1130impl<E: EntityTrait> ModelKey<E> for UnitPk<E> {
1131    type Type = Value;
1132    fn get(&self, model: &E::Model) -> Self::Type {
1133        model.get(self.0)
1134    }
1135}
1136
1137impl<E: EntityTrait> ModelKey<E> for PairPk<E> {
1138    type Type = (Value, Value);
1139    fn get(&self, model: &E::Model) -> Self::Type {
1140        (model.get(self.0), model.get(self.1))
1141    }
1142}
1143
1144impl<E: EntityTrait> ModelKey<E> for TuplePk<E> {
1145    type Type = Vec<Value>;
1146    fn get(&self, model: &E::Model) -> Self::Type {
1147        let mut key = Vec::new();
1148        for col in self.0.iter() {
1149            key.push(model.get(*col));
1150        }
1151        key
1152    }
1153}
1154
1155fn consolidate_query_result_of<L, R, KEY: ModelKey<L>>(
1156    mut rows: Vec<(L::Model, Option<R::Model>)>,
1157    model_key: KEY,
1158) -> Vec<(L::Model, Vec<R::Model>)>
1159where
1160    L: EntityTrait,
1161    R: EntityTrait,
1162{
1163    let mut hashmap: HashMap<KEY::Type, Vec<R::Model>> =
1164        rows.iter_mut().fold(HashMap::new(), |mut acc, row| {
1165            let key = model_key.get(&row.0);
1166            if let Some(value) = row.1.take() {
1167                let vec: Option<&mut Vec<R::Model>> = acc.get_mut(&key);
1168                if let Some(vec) = vec {
1169                    vec.push(value)
1170                } else {
1171                    acc.insert(key, vec![value]);
1172                }
1173            } else {
1174                acc.entry(key).or_default();
1175            }
1176
1177            acc
1178        });
1179
1180    rows.into_iter()
1181        .filter_map(|(l_model, _)| {
1182            let l_pk = model_key.get(&l_model);
1183            let r_models = hashmap.remove(&l_pk);
1184            r_models.map(|r_models| (l_model, r_models))
1185        })
1186        .collect()
1187}
1188
1189/// This is the legacy consolidate algorithm. Kept for reference
1190#[allow(dead_code)]
1191fn consolidate_query_result_of_ordered_rows<L, R>(
1192    rows: Vec<(L::Model, Option<R::Model>)>,
1193) -> Vec<(L::Model, Vec<R::Model>)>
1194where
1195    L: EntityTrait,
1196    R: EntityTrait,
1197{
1198    let mut acc: Vec<(L::Model, Vec<R::Model>)> = Vec::new();
1199    for (l, r) in rows {
1200        if let Some((last_l, last_r)) = acc.last_mut() {
1201            let mut same_l = true;
1202            for pk_col in <L::PrimaryKey as Iterable>::iter() {
1203                let col = pk_col.into_column();
1204                let val = l.get(col);
1205                let last_val = last_l.get(col);
1206                if !val.eq(&last_val) {
1207                    same_l = false;
1208                    break;
1209                }
1210            }
1211            if same_l {
1212                if let Some(r) = r {
1213                    last_r.push(r);
1214                    continue;
1215                }
1216            }
1217        }
1218        let rows = match r {
1219            Some(r) => vec![r],
1220            None => vec![],
1221        };
1222        acc.push((l, rows));
1223    }
1224    acc
1225}
1226
1227#[cfg(test)]
1228mod tests {
1229    use pretty_assertions::assert_eq;
1230
1231    fn cake_fruit_model(
1232        cake_id: i32,
1233        fruit_id: i32,
1234    ) -> (
1235        sea_orm::tests_cfg::cake::Model,
1236        sea_orm::tests_cfg::fruit::Model,
1237    ) {
1238        (cake_model(cake_id), fruit_model(fruit_id, Some(cake_id)))
1239    }
1240
1241    fn cake_model(id: i32) -> sea_orm::tests_cfg::cake::Model {
1242        let name = match id {
1243            1 => "apple cake",
1244            2 => "orange cake",
1245            3 => "fruit cake",
1246            4 => "chocolate cake",
1247            _ => "",
1248        }
1249        .to_string();
1250        sea_orm::tests_cfg::cake::Model { id, name }
1251    }
1252
1253    fn filling_model(id: i32) -> sea_orm::tests_cfg::filling::Model {
1254        let name = match id {
1255            1 => "apple juice",
1256            2 => "orange jam",
1257            3 => "fruit",
1258            4 => "chocolate crust",
1259            _ => "",
1260        }
1261        .to_string();
1262        sea_orm::tests_cfg::filling::Model {
1263            id,
1264            name,
1265            vendor_id: Some(1),
1266            ignored_attr: 0,
1267        }
1268    }
1269
1270    fn cake_filling_models(
1271        cake_id: i32,
1272        filling_id: i32,
1273    ) -> (
1274        sea_orm::tests_cfg::cake::Model,
1275        sea_orm::tests_cfg::filling::Model,
1276    ) {
1277        (cake_model(cake_id), filling_model(filling_id))
1278    }
1279
1280    fn fruit_model(id: i32, cake_id: Option<i32>) -> sea_orm::tests_cfg::fruit::Model {
1281        let name = match id {
1282            1 => "apple",
1283            2 => "orange",
1284            3 => "grape",
1285            4 => "strawberry",
1286            _ => "",
1287        }
1288        .to_string();
1289        sea_orm::tests_cfg::fruit::Model { id, name, cake_id }
1290    }
1291
1292    fn cake_vendor_link(
1293        cake_id: i32,
1294        vendor_id: i32,
1295    ) -> (
1296        sea_orm::tests_cfg::cake::Model,
1297        sea_orm::tests_cfg::vendor::Model,
1298    ) {
1299        (cake_model(cake_id), vendor_model(vendor_id))
1300    }
1301
1302    fn vendor_model(id: i32) -> sea_orm::tests_cfg::vendor::Model {
1303        let name = match id {
1304            1 => "Apollo",
1305            2 => "Benny",
1306            3 => "Christine",
1307            4 => "David",
1308            _ => "",
1309        }
1310        .to_string();
1311        sea_orm::tests_cfg::vendor::Model { id, name }
1312    }
1313
1314    #[smol_potat::test]
1315    pub async fn also_related() -> Result<(), sea_orm::DbErr> {
1316        use sea_orm::tests_cfg::*;
1317        use sea_orm::{DbBackend, EntityTrait, MockDatabase, Statement, Transaction};
1318
1319        let db = MockDatabase::new(DbBackend::Postgres)
1320            .append_query_results([[cake_fruit_model(1, 1)]])
1321            .into_connection();
1322
1323        assert_eq!(
1324            Cake::find().find_also_related(Fruit).all(&db).await?,
1325            [(cake_model(1), Some(fruit_model(1, Some(1))))]
1326        );
1327
1328        assert_eq!(
1329            db.into_transaction_log(),
1330            [Transaction::many([Statement::from_sql_and_values(
1331                DbBackend::Postgres,
1332                [
1333                    r#"SELECT "cake"."id" AS "A_id", "cake"."name" AS "A_name","#,
1334                    r#""fruit"."id" AS "B_id", "fruit"."name" AS "B_name", "fruit"."cake_id" AS "B_cake_id""#,
1335                    r#"FROM "cake""#,
1336                    r#"LEFT JOIN "fruit" ON "cake"."id" = "fruit"."cake_id""#,
1337                ]
1338                .join(" ")
1339                .as_str(),
1340                []
1341            ),])]
1342        );
1343
1344        Ok(())
1345    }
1346
1347    #[smol_potat::test]
1348    pub async fn also_related_2() -> Result<(), sea_orm::DbErr> {
1349        use sea_orm::tests_cfg::*;
1350        use sea_orm::{DbBackend, EntityTrait, MockDatabase};
1351
1352        let db = MockDatabase::new(DbBackend::Postgres)
1353            .append_query_results([[cake_fruit_model(1, 1), cake_fruit_model(1, 2)]])
1354            .into_connection();
1355
1356        assert_eq!(
1357            Cake::find().find_also_related(Fruit).all(&db).await?,
1358            [
1359                (cake_model(1), Some(fruit_model(1, Some(1)))),
1360                (cake_model(1), Some(fruit_model(2, Some(1))))
1361            ]
1362        );
1363
1364        Ok(())
1365    }
1366
1367    #[smol_potat::test]
1368    pub async fn also_related_3() -> Result<(), sea_orm::DbErr> {
1369        use sea_orm::tests_cfg::*;
1370        use sea_orm::{DbBackend, EntityTrait, MockDatabase};
1371
1372        let db = MockDatabase::new(DbBackend::Postgres)
1373            .append_query_results([[
1374                cake_fruit_model(1, 1),
1375                cake_fruit_model(1, 2),
1376                cake_fruit_model(2, 3),
1377            ]])
1378            .into_connection();
1379
1380        assert_eq!(
1381            Cake::find().find_also_related(Fruit).all(&db).await?,
1382            [
1383                (cake_model(1), Some(fruit_model(1, Some(1)))),
1384                (cake_model(1), Some(fruit_model(2, Some(1)))),
1385                (cake_model(2), Some(fruit_model(3, Some(2))))
1386            ]
1387        );
1388
1389        Ok(())
1390    }
1391
1392    #[smol_potat::test]
1393    pub async fn also_related_4() -> Result<(), sea_orm::DbErr> {
1394        use sea_orm::tests_cfg::*;
1395        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1396
1397        let db = MockDatabase::new(DbBackend::Postgres)
1398            .append_query_results([[
1399                cake_fruit_model(1, 1).into_mock_row(),
1400                cake_fruit_model(1, 2).into_mock_row(),
1401                cake_fruit_model(2, 3).into_mock_row(),
1402                (cake_model(3), None::<fruit::Model>).into_mock_row(),
1403            ]])
1404            .into_connection();
1405
1406        assert_eq!(
1407            Cake::find().find_also_related(Fruit).all(&db).await?,
1408            [
1409                (cake_model(1), Some(fruit_model(1, Some(1)))),
1410                (cake_model(1), Some(fruit_model(2, Some(1)))),
1411                (cake_model(2), Some(fruit_model(3, Some(2)))),
1412                (cake_model(3), None)
1413            ]
1414        );
1415
1416        Ok(())
1417    }
1418
1419    #[smol_potat::test]
1420    pub async fn also_related_many_to_many() -> Result<(), sea_orm::DbErr> {
1421        use sea_orm::tests_cfg::*;
1422        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1423
1424        let db = MockDatabase::new(DbBackend::Postgres)
1425            .append_query_results([[
1426                cake_filling_models(1, 1).into_mock_row(),
1427                cake_filling_models(1, 2).into_mock_row(),
1428                cake_filling_models(2, 2).into_mock_row(),
1429            ]])
1430            .into_connection();
1431
1432        assert_eq!(
1433            Cake::find().find_also_related(Filling).all(&db).await?,
1434            [
1435                (cake_model(1), Some(filling_model(1))),
1436                (cake_model(1), Some(filling_model(2))),
1437                (cake_model(2), Some(filling_model(2))),
1438            ]
1439        );
1440
1441        Ok(())
1442    }
1443
1444    #[smol_potat::test]
1445    pub async fn also_related_many_to_many_2() -> Result<(), sea_orm::DbErr> {
1446        use sea_orm::tests_cfg::*;
1447        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1448
1449        let db = MockDatabase::new(DbBackend::Postgres)
1450            .append_query_results([[
1451                cake_filling_models(1, 1).into_mock_row(),
1452                cake_filling_models(1, 2).into_mock_row(),
1453                cake_filling_models(2, 2).into_mock_row(),
1454                (cake_model(3), None::<filling::Model>).into_mock_row(),
1455            ]])
1456            .into_connection();
1457
1458        assert_eq!(
1459            Cake::find().find_also_related(Filling).all(&db).await?,
1460            [
1461                (cake_model(1), Some(filling_model(1))),
1462                (cake_model(1), Some(filling_model(2))),
1463                (cake_model(2), Some(filling_model(2))),
1464                (cake_model(3), None)
1465            ]
1466        );
1467
1468        Ok(())
1469    }
1470
1471    #[smol_potat::test]
1472    pub async fn with_related() -> Result<(), sea_orm::DbErr> {
1473        use sea_orm::tests_cfg::*;
1474        use sea_orm::{DbBackend, EntityTrait, MockDatabase, Statement, Transaction};
1475
1476        let db = MockDatabase::new(DbBackend::Postgres)
1477            .append_query_results([[
1478                cake_fruit_model(1, 1),
1479                cake_fruit_model(2, 2),
1480                cake_fruit_model(2, 3),
1481            ]])
1482            .into_connection();
1483
1484        assert_eq!(
1485            Cake::find().find_with_related(Fruit).all(&db).await?,
1486            [
1487                (cake_model(1), vec![fruit_model(1, Some(1))]),
1488                (
1489                    cake_model(2),
1490                    vec![fruit_model(2, Some(2)), fruit_model(3, Some(2))]
1491                )
1492            ]
1493        );
1494
1495        assert_eq!(
1496            db.into_transaction_log(),
1497            [Transaction::many([Statement::from_sql_and_values(
1498                DbBackend::Postgres,
1499                [
1500                    r#"SELECT "cake"."id" AS "A_id", "cake"."name" AS "A_name","#,
1501                    r#""fruit"."id" AS "B_id", "fruit"."name" AS "B_name", "fruit"."cake_id" AS "B_cake_id""#,
1502                    r#"FROM "cake""#,
1503                    r#"LEFT JOIN "fruit" ON "cake"."id" = "fruit"."cake_id""#,
1504                    r#"ORDER BY "cake"."id" ASC"#
1505                ]
1506                .join(" ")
1507                .as_str(),
1508                []
1509            ),])]
1510        );
1511
1512        Ok(())
1513    }
1514
1515    #[smol_potat::test]
1516    pub async fn with_related_2() -> Result<(), sea_orm::DbErr> {
1517        use sea_orm::tests_cfg::*;
1518        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1519
1520        let db = MockDatabase::new(DbBackend::Postgres)
1521            .append_query_results([[
1522                cake_fruit_model(1, 1).into_mock_row(),
1523                cake_fruit_model(2, 2).into_mock_row(),
1524                cake_fruit_model(2, 3).into_mock_row(),
1525                cake_fruit_model(2, 4).into_mock_row(),
1526            ]])
1527            .into_connection();
1528
1529        assert_eq!(
1530            Cake::find().find_with_related(Fruit).all(&db).await?,
1531            [
1532                (cake_model(1), vec![fruit_model(1, Some(1)),]),
1533                (
1534                    cake_model(2),
1535                    vec![
1536                        fruit_model(2, Some(2)),
1537                        fruit_model(3, Some(2)),
1538                        fruit_model(4, Some(2)),
1539                    ]
1540                ),
1541            ]
1542        );
1543
1544        Ok(())
1545    }
1546
1547    #[smol_potat::test]
1548    pub async fn with_related_empty() -> Result<(), sea_orm::DbErr> {
1549        use sea_orm::tests_cfg::*;
1550        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1551
1552        let db = MockDatabase::new(DbBackend::Postgres)
1553            .append_query_results([[
1554                cake_fruit_model(1, 1).into_mock_row(),
1555                cake_fruit_model(2, 2).into_mock_row(),
1556                cake_fruit_model(2, 3).into_mock_row(),
1557                cake_fruit_model(2, 4).into_mock_row(),
1558                (cake_model(3), None::<fruit::Model>).into_mock_row(),
1559            ]])
1560            .into_connection();
1561
1562        assert_eq!(
1563            Cake::find().find_with_related(Fruit).all(&db).await?,
1564            [
1565                (cake_model(1), vec![fruit_model(1, Some(1)),]),
1566                (
1567                    cake_model(2),
1568                    vec![
1569                        fruit_model(2, Some(2)),
1570                        fruit_model(3, Some(2)),
1571                        fruit_model(4, Some(2)),
1572                    ]
1573                ),
1574                (cake_model(3), vec![])
1575            ]
1576        );
1577
1578        Ok(())
1579    }
1580
1581    #[smol_potat::test]
1582    pub async fn with_related_many_to_many() -> Result<(), sea_orm::DbErr> {
1583        use sea_orm::tests_cfg::*;
1584        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1585
1586        let db = MockDatabase::new(DbBackend::Postgres)
1587            .append_query_results([[
1588                cake_filling_models(1, 1).into_mock_row(),
1589                cake_filling_models(1, 2).into_mock_row(),
1590                cake_filling_models(2, 2).into_mock_row(),
1591            ]])
1592            .into_connection();
1593
1594        assert_eq!(
1595            Cake::find().find_with_related(Filling).all(&db).await?,
1596            [
1597                (cake_model(1), vec![filling_model(1), filling_model(2)]),
1598                (cake_model(2), vec![filling_model(2)]),
1599            ]
1600        );
1601
1602        Ok(())
1603    }
1604
1605    #[smol_potat::test]
1606    pub async fn with_related_many_to_many_2() -> Result<(), sea_orm::DbErr> {
1607        use sea_orm::tests_cfg::*;
1608        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1609
1610        let db = MockDatabase::new(DbBackend::Postgres)
1611            .append_query_results([[
1612                cake_filling_models(1, 1).into_mock_row(),
1613                cake_filling_models(1, 2).into_mock_row(),
1614                cake_filling_models(2, 2).into_mock_row(),
1615                (cake_model(3), None::<filling::Model>).into_mock_row(),
1616            ]])
1617            .into_connection();
1618
1619        assert_eq!(
1620            Cake::find().find_with_related(Filling).all(&db).await?,
1621            [
1622                (cake_model(1), vec![filling_model(1), filling_model(2)]),
1623                (cake_model(2), vec![filling_model(2)]),
1624                (cake_model(3), vec![])
1625            ]
1626        );
1627
1628        Ok(())
1629    }
1630
1631    #[smol_potat::test]
1632    pub async fn also_linked_base() -> Result<(), sea_orm::DbErr> {
1633        use sea_orm::tests_cfg::*;
1634        use sea_orm::{DbBackend, EntityTrait, MockDatabase, Statement, Transaction};
1635
1636        let db = MockDatabase::new(DbBackend::Postgres)
1637            .append_query_results([[cake_vendor_link(1, 1)]])
1638            .into_connection();
1639
1640        assert_eq!(
1641            Cake::find()
1642                .find_also_linked(entity_linked::CakeToFillingVendor)
1643                .all(&db)
1644                .await?,
1645            [(cake_model(1), Some(vendor_model(1)))]
1646        );
1647
1648        assert_eq!(
1649            db.into_transaction_log(),
1650            [Transaction::many([Statement::from_sql_and_values(
1651                DbBackend::Postgres,
1652                [
1653                    r#"SELECT "cake"."id" AS "A_id", "cake"."name" AS "A_name","#,
1654                    r#""r2"."id" AS "B_id", "r2"."name" AS "B_name""#,
1655                    r#"FROM "cake""#,
1656                    r#"LEFT JOIN "cake_filling" AS "r0" ON "cake"."id" = "r0"."cake_id""#,
1657                    r#"LEFT JOIN "filling" AS "r1" ON "r0"."filling_id" = "r1"."id""#,
1658                    r#"LEFT JOIN "vendor" AS "r2" ON "r1"."vendor_id" = "r2"."id""#,
1659                ]
1660                .join(" ")
1661                .as_str(),
1662                []
1663            ),])]
1664        );
1665
1666        Ok(())
1667    }
1668
1669    #[smol_potat::test]
1670    pub async fn also_linked_same_cake() -> Result<(), sea_orm::DbErr> {
1671        use sea_orm::tests_cfg::*;
1672        use sea_orm::{DbBackend, EntityTrait, MockDatabase};
1673
1674        let db = MockDatabase::new(DbBackend::Postgres)
1675            .append_query_results([[
1676                cake_vendor_link(1, 1),
1677                cake_vendor_link(1, 2),
1678                cake_vendor_link(2, 3),
1679            ]])
1680            .into_connection();
1681
1682        assert_eq!(
1683            Cake::find()
1684                .find_also_linked(entity_linked::CakeToFillingVendor)
1685                .all(&db)
1686                .await?,
1687            [
1688                (cake_model(1), Some(vendor_model(1))),
1689                (cake_model(1), Some(vendor_model(2))),
1690                (cake_model(2), Some(vendor_model(3)))
1691            ]
1692        );
1693
1694        Ok(())
1695    }
1696
1697    #[smol_potat::test]
1698    pub async fn also_linked_same_vendor() -> Result<(), sea_orm::DbErr> {
1699        use sea_orm::tests_cfg::*;
1700        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1701
1702        let db = MockDatabase::new(DbBackend::Postgres)
1703            .append_query_results([[
1704                cake_vendor_link(1, 1).into_mock_row(),
1705                cake_vendor_link(2, 1).into_mock_row(),
1706                cake_vendor_link(3, 2).into_mock_row(),
1707            ]])
1708            .into_connection();
1709
1710        assert_eq!(
1711            Cake::find()
1712                .find_also_linked(entity_linked::CakeToFillingVendor)
1713                .all(&db)
1714                .await?,
1715            [
1716                (cake_model(1), Some(vendor_model(1))),
1717                (cake_model(2), Some(vendor_model(1))),
1718                (cake_model(3), Some(vendor_model(2))),
1719            ]
1720        );
1721
1722        Ok(())
1723    }
1724
1725    #[smol_potat::test]
1726    pub async fn also_linked_many_to_many() -> Result<(), sea_orm::DbErr> {
1727        use sea_orm::tests_cfg::*;
1728        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1729
1730        let db = MockDatabase::new(DbBackend::Postgres)
1731            .append_query_results([[
1732                cake_vendor_link(1, 1).into_mock_row(),
1733                cake_vendor_link(1, 2).into_mock_row(),
1734                cake_vendor_link(1, 3).into_mock_row(),
1735                cake_vendor_link(2, 1).into_mock_row(),
1736                cake_vendor_link(2, 2).into_mock_row(),
1737            ]])
1738            .into_connection();
1739
1740        assert_eq!(
1741            Cake::find()
1742                .find_also_linked(entity_linked::CakeToFillingVendor)
1743                .all(&db)
1744                .await?,
1745            [
1746                (cake_model(1), Some(vendor_model(1))),
1747                (cake_model(1), Some(vendor_model(2))),
1748                (cake_model(1), Some(vendor_model(3))),
1749                (cake_model(2), Some(vendor_model(1))),
1750                (cake_model(2), Some(vendor_model(2))),
1751            ]
1752        );
1753
1754        Ok(())
1755    }
1756
1757    #[smol_potat::test]
1758    pub async fn also_linked_empty() -> Result<(), sea_orm::DbErr> {
1759        use sea_orm::tests_cfg::*;
1760        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1761
1762        let db = MockDatabase::new(DbBackend::Postgres)
1763            .append_query_results([[
1764                cake_vendor_link(1, 1).into_mock_row(),
1765                cake_vendor_link(2, 2).into_mock_row(),
1766                cake_vendor_link(3, 3).into_mock_row(),
1767                (cake_model(4), None::<vendor::Model>).into_mock_row(),
1768            ]])
1769            .into_connection();
1770
1771        assert_eq!(
1772            Cake::find()
1773                .find_also_linked(entity_linked::CakeToFillingVendor)
1774                .all(&db)
1775                .await?,
1776            [
1777                (cake_model(1), Some(vendor_model(1))),
1778                (cake_model(2), Some(vendor_model(2))),
1779                (cake_model(3), Some(vendor_model(3))),
1780                (cake_model(4), None)
1781            ]
1782        );
1783
1784        Ok(())
1785    }
1786
1787    #[smol_potat::test]
1788    pub async fn with_linked_base() -> Result<(), sea_orm::DbErr> {
1789        use sea_orm::tests_cfg::*;
1790        use sea_orm::{DbBackend, EntityTrait, MockDatabase, Statement, Transaction};
1791
1792        let db = MockDatabase::new(DbBackend::Postgres)
1793            .append_query_results([[
1794                cake_vendor_link(1, 1),
1795                cake_vendor_link(2, 2),
1796                cake_vendor_link(2, 3),
1797            ]])
1798            .into_connection();
1799
1800        assert_eq!(
1801            Cake::find()
1802                .find_with_linked(entity_linked::CakeToFillingVendor)
1803                .all(&db)
1804                .await?,
1805            [
1806                (cake_model(1), vec![vendor_model(1)]),
1807                (cake_model(2), vec![vendor_model(2), vendor_model(3)])
1808            ]
1809        );
1810
1811        assert_eq!(
1812            db.into_transaction_log(),
1813            [Transaction::many([Statement::from_sql_and_values(
1814                DbBackend::Postgres,
1815                [
1816                    r#"SELECT "cake"."id" AS "A_id", "cake"."name" AS "A_name","#,
1817                    r#""r2"."id" AS "B_id", "r2"."name" AS "B_name" FROM "cake""#,
1818                    r#"LEFT JOIN "cake_filling" AS "r0" ON "cake"."id" = "r0"."cake_id""#,
1819                    r#"LEFT JOIN "filling" AS "r1" ON "r0"."filling_id" = "r1"."id""#,
1820                    r#"LEFT JOIN "vendor" AS "r2" ON "r1"."vendor_id" = "r2"."id""#,
1821                ]
1822                .join(" ")
1823                .as_str(),
1824                []
1825            ),])]
1826        );
1827
1828        Ok(())
1829    }
1830
1831    #[smol_potat::test]
1832    pub async fn with_linked_same_vendor() -> Result<(), sea_orm::DbErr> {
1833        use sea_orm::tests_cfg::*;
1834        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1835
1836        let db = MockDatabase::new(DbBackend::Postgres)
1837            .append_query_results([[
1838                cake_vendor_link(1, 1).into_mock_row(),
1839                cake_vendor_link(2, 2).into_mock_row(),
1840                cake_vendor_link(3, 2).into_mock_row(),
1841            ]])
1842            .into_connection();
1843
1844        assert_eq!(
1845            Cake::find()
1846                .find_with_linked(entity_linked::CakeToFillingVendor)
1847                .all(&db)
1848                .await?,
1849            [
1850                (cake_model(1), vec![vendor_model(1)]),
1851                (cake_model(2), vec![vendor_model(2)]),
1852                (cake_model(3), vec![vendor_model(2)])
1853            ]
1854        );
1855
1856        Ok(())
1857    }
1858
1859    #[smol_potat::test]
1860    pub async fn with_linked_empty() -> Result<(), sea_orm::DbErr> {
1861        use sea_orm::tests_cfg::*;
1862        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1863
1864        let db = MockDatabase::new(DbBackend::Postgres)
1865            .append_query_results([[
1866                cake_vendor_link(1, 1).into_mock_row(),
1867                cake_vendor_link(2, 1).into_mock_row(),
1868                cake_vendor_link(2, 2).into_mock_row(),
1869                (cake_model(3), None::<vendor::Model>).into_mock_row(),
1870            ]])
1871            .into_connection();
1872
1873        assert_eq!(
1874            Cake::find()
1875                .find_with_linked(entity_linked::CakeToFillingVendor)
1876                .all(&db)
1877                .await?,
1878            [
1879                (cake_model(1), vec![vendor_model(1)]),
1880                (cake_model(2), vec![vendor_model(1), vendor_model(2)]),
1881                (cake_model(3), vec![])
1882            ]
1883        );
1884
1885        Ok(())
1886    }
1887
1888    // normally would not happen
1889    #[smol_potat::test]
1890    pub async fn with_linked_repeated() -> Result<(), sea_orm::DbErr> {
1891        use sea_orm::tests_cfg::*;
1892        use sea_orm::{DbBackend, EntityTrait, IntoMockRow, MockDatabase};
1893
1894        let db = MockDatabase::new(DbBackend::Postgres)
1895            .append_query_results([[
1896                cake_vendor_link(1, 1).into_mock_row(),
1897                cake_vendor_link(1, 1).into_mock_row(),
1898                cake_vendor_link(2, 1).into_mock_row(),
1899                cake_vendor_link(2, 2).into_mock_row(),
1900            ]])
1901            .into_connection();
1902
1903        assert_eq!(
1904            Cake::find()
1905                .find_with_linked(entity_linked::CakeToFillingVendor)
1906                .all(&db)
1907                .await?,
1908            [
1909                (cake_model(1), vec![vendor_model(1), vendor_model(1)]),
1910                (cake_model(2), vec![vendor_model(1), vendor_model(2)]),
1911            ]
1912        );
1913
1914        Ok(())
1915    }
1916}