sea_orm/query/
loader.rs

1use super::get_key_from_model;
2use crate::{
3    ColumnTrait, Condition, ConnectionTrait, DbBackend, DbErr, EntityTrait, Identity, JoinType,
4    ModelTrait, QueryFilter, QuerySelect, Related, RelatedSelfVia, RelationDef, RelationTrait,
5    RelationType, Select, dynamic, query::column_tuple_in_condition, query_err,
6};
7use sea_query::{ColumnRef, DynIden, Expr, ExprTrait, IntoColumnRef, TableRef, ValueTuple};
8use std::{collections::HashMap, str::FromStr};
9
10// TODO: Replace DynIden::inner with a better API that without clone
11
12/// Entity, or a Select<Entity>; to be used as parameters in [`LoaderTrait`]
13pub trait EntityOrSelect<E: EntityTrait>: Send {
14    /// If self is Entity, use Entity::find()
15    fn select(self) -> Select<E>;
16}
17
18type LoaderEntity<T> = <<T as LoaderTrait>::Model as ModelTrait>::Entity;
19type LoaderModel<T> = <<<T as LoaderTrait>::Model as ModelTrait>::Entity as EntityTrait>::Model;
20type LoaderRelation<T> =
21    <<<T as LoaderTrait>::Model as ModelTrait>::Entity as EntityTrait>::Relation;
22
23/// This trait implements the Data Loader API
24#[async_trait::async_trait]
25pub trait LoaderTrait {
26    /// Source model
27    type Model: ModelTrait;
28
29    /// Used to eager load self_ref relations
30    async fn load_self<S, C>(
31        &self,
32        stmt: S,
33        relation_enum: LoaderRelation<Self>,
34        db: &C,
35    ) -> Result<Vec<Option<LoaderModel<Self>>>, DbErr>
36    where
37        C: ConnectionTrait,
38        LoaderModel<Self>: Send + Sync,
39        LoaderRelation<Self>: Send,
40        S: EntityOrSelect<LoaderEntity<Self>>;
41
42    /// Used to eager load self_ref relations in reverse, output is `Vec<Model>` instead of
43    /// `Option<Model>` of `load_self`.
44    async fn load_self_many<S, C>(
45        &self,
46        stmt: S,
47        relation_enum: LoaderRelation<Self>,
48        db: &C,
49    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
50    where
51        C: ConnectionTrait,
52        LoaderModel<Self>: Send + Sync,
53        LoaderRelation<Self>: Send,
54        S: EntityOrSelect<LoaderEntity<Self>>;
55
56    /// Used to eager load self_ref + via relations
57    async fn load_self_via<V, C>(
58        &self,
59        via: V,
60        db: &C,
61    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
62    where
63        C: ConnectionTrait,
64        V: EntityTrait,
65        LoaderModel<Self>: Send + Sync,
66        LoaderEntity<Self>: RelatedSelfVia<V>;
67
68    /// Used to eager load self_ref + via relations, but in reverse
69    async fn load_self_via_rev<V, C>(
70        &self,
71        via: V,
72        db: &C,
73    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
74    where
75        C: ConnectionTrait,
76        V: EntityTrait,
77        LoaderModel<Self>: Send + Sync,
78        LoaderEntity<Self>: RelatedSelfVia<V>;
79
80    /// Used to eager load has_one relations
81    async fn load_one<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::Model>>, DbErr>
82    where
83        C: ConnectionTrait,
84        R: EntityTrait,
85        R::Model: Send + Sync,
86        S: EntityOrSelect<R>,
87        <Self::Model as ModelTrait>::Entity: Related<R>;
88
89    /// Used to eager load has_many relations
90    async fn load_many<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::Model>>, DbErr>
91    where
92        C: ConnectionTrait,
93        R: EntityTrait,
94        R::Model: Send + Sync,
95        S: EntityOrSelect<R>,
96        <Self::Model as ModelTrait>::Entity: Related<R>;
97
98    /// Used to eager load many_to_many relations. In SeaORM 2.0 `load_many` already support M-N
99    /// relations so this method is not needed, only kept as legacy.
100    async fn load_many_to_many<R, S, V, C>(
101        &self,
102        stmt: S,
103        via: V,
104        db: &C,
105    ) -> Result<Vec<Vec<R::Model>>, DbErr>
106    where
107        C: ConnectionTrait,
108        R: EntityTrait,
109        R::Model: Send + Sync,
110        S: EntityOrSelect<R>,
111        V: EntityTrait,
112        V::Model: Send + Sync,
113        <Self::Model as ModelTrait>::Entity: Related<R>;
114}
115
116type LoaderExEntity<T> = <<T as LoaderTraitEx>::Model as ModelTrait>::Entity;
117type LoaderExModel<T> = <<<T as LoaderTraitEx>::Model as ModelTrait>::Entity as EntityTrait>::Model;
118type LoaderExModelEx<T> =
119    <<<T as LoaderTraitEx>::Model as ModelTrait>::Entity as EntityTrait>::ModelEx;
120type LoaderExRelation<T> =
121    <<<T as LoaderTraitEx>::Model as ModelTrait>::Entity as EntityTrait>::Relation;
122
123#[doc(hidden)]
124#[async_trait::async_trait]
125pub trait LoaderTraitEx {
126    type Model: ModelTrait;
127
128    async fn load_self_ex<S, C>(
129        &self,
130        stmt: S,
131        relation_enum: LoaderExRelation<Self>,
132        db: &C,
133    ) -> Result<Vec<Option<LoaderExModelEx<Self>>>, DbErr>
134    where
135        C: ConnectionTrait,
136        LoaderExModel<Self>: Send + Sync,
137        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
138        LoaderExRelation<Self>: Send,
139        S: EntityOrSelect<LoaderExEntity<Self>>;
140
141    async fn load_self_many_ex<S, C>(
142        &self,
143        stmt: S,
144        relation_enum: LoaderExRelation<Self>,
145        db: &C,
146    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
147    where
148        C: ConnectionTrait,
149        LoaderExModel<Self>: Send + Sync,
150        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
151        LoaderExRelation<Self>: Send,
152        S: EntityOrSelect<LoaderExEntity<Self>>;
153
154    async fn load_self_via_ex<V, C>(
155        &self,
156        via: V,
157        is_reverse: bool,
158        db: &C,
159    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
160    where
161        C: ConnectionTrait,
162        V: EntityTrait,
163        LoaderExModel<Self>: Send + Sync,
164        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
165        LoaderExEntity<Self>: RelatedSelfVia<V>;
166
167    async fn load_one_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::ModelEx>>, DbErr>
168    where
169        C: ConnectionTrait,
170        R: EntityTrait,
171        R::Model: Send + Sync,
172        S: EntityOrSelect<R>,
173        R::ModelEx: From<R::Model>,
174        <Self::Model as ModelTrait>::Entity: Related<R>;
175
176    async fn load_many_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::ModelEx>>, DbErr>
177    where
178        C: ConnectionTrait,
179        R: EntityTrait,
180        R::Model: Send + Sync,
181        S: EntityOrSelect<R>,
182        R::ModelEx: From<R::Model>,
183        <Self::Model as ModelTrait>::Entity: Related<R>;
184}
185
186type NestedEntity<T> = <<T as NestedLoaderTrait>::Model as ModelTrait>::Entity;
187type NestedModel<T> =
188    <<<T as NestedLoaderTrait>::Model as ModelTrait>::Entity as EntityTrait>::Model;
189type NestedModelEx<T> =
190    <<<T as NestedLoaderTrait>::Model as ModelTrait>::Entity as EntityTrait>::ModelEx;
191type NestedLoaderRelation<T> =
192    <<<T as NestedLoaderTrait>::Model as ModelTrait>::Entity as EntityTrait>::Relation;
193
194#[doc(hidden)]
195#[async_trait::async_trait]
196pub trait NestedLoaderTrait {
197    type Model: ModelTrait;
198
199    async fn load_self_ex<S, C>(
200        &self,
201        stmt: S,
202        relation_enum: NestedLoaderRelation<Self>,
203        db: &C,
204    ) -> Result<Vec<Vec<Option<NestedModelEx<Self>>>>, DbErr>
205    where
206        C: ConnectionTrait,
207        NestedModel<Self>: Send + Sync,
208        NestedModelEx<Self>: From<NestedModel<Self>>,
209        NestedLoaderRelation<Self>: Send,
210        S: EntityOrSelect<<<Self as NestedLoaderTrait>::Model as ModelTrait>::Entity>;
211
212    async fn load_self_many_ex<S, C>(
213        &self,
214        stmt: S,
215        relation_enum: NestedLoaderRelation<Self>,
216        db: &C,
217    ) -> Result<Vec<Vec<Vec<NestedModelEx<Self>>>>, DbErr>
218    where
219        C: ConnectionTrait,
220        NestedModel<Self>: Send + Sync,
221        NestedModelEx<Self>: From<NestedModel<Self>>,
222        NestedLoaderRelation<Self>: Send,
223        S: EntityOrSelect<<<Self as NestedLoaderTrait>::Model as ModelTrait>::Entity>;
224
225    async fn load_self_via_ex<V, C>(
226        &self,
227        via: V,
228        is_reverse: bool,
229        db: &C,
230    ) -> Result<Vec<Vec<Vec<NestedModelEx<Self>>>>, DbErr>
231    where
232        C: ConnectionTrait,
233        V: EntityTrait,
234        NestedModel<Self>: Send + Sync,
235        NestedModelEx<Self>: From<NestedModel<Self>>,
236        NestedEntity<Self>: RelatedSelfVia<V>;
237
238    async fn load_one_ex<R, S, C>(
239        &self,
240        stmt: S,
241        db: &C,
242    ) -> Result<Vec<Vec<Option<R::ModelEx>>>, DbErr>
243    where
244        C: ConnectionTrait,
245        R: EntityTrait,
246        R::Model: Send + Sync,
247        S: EntityOrSelect<R>,
248        R::ModelEx: From<R::Model>,
249        <Self::Model as ModelTrait>::Entity: Related<R>;
250
251    async fn load_many_ex<R, S, C>(
252        &self,
253        stmt: S,
254        db: &C,
255    ) -> Result<Vec<Vec<Vec<R::ModelEx>>>, DbErr>
256    where
257        C: ConnectionTrait,
258        R: EntityTrait,
259        R::Model: Send + Sync,
260        S: EntityOrSelect<R>,
261        R::ModelEx: From<R::Model>,
262        <Self::Model as ModelTrait>::Entity: Related<R>;
263}
264
265impl<E> EntityOrSelect<E> for E
266where
267    E: EntityTrait,
268{
269    fn select(self) -> Select<E> {
270        E::find().order_by_id_asc()
271    }
272}
273
274impl<E> EntityOrSelect<E> for Select<E>
275where
276    E: EntityTrait,
277{
278    fn select(self) -> Select<E> {
279        self
280    }
281}
282
283#[async_trait::async_trait]
284impl<M> LoaderTrait for Vec<M>
285where
286    M: ModelTrait + Sync,
287{
288    type Model = M;
289
290    async fn load_self<S, C>(
291        &self,
292        stmt: S,
293        relation_enum: LoaderRelation<Self>,
294        db: &C,
295    ) -> Result<Vec<Option<LoaderModel<Self>>>, DbErr>
296    where
297        C: ConnectionTrait,
298        LoaderModel<Self>: Send + Sync,
299        LoaderRelation<Self>: Send,
300        S: EntityOrSelect<LoaderEntity<Self>>,
301    {
302        LoaderTrait::load_self(&self.as_slice(), stmt, relation_enum, db).await
303    }
304
305    async fn load_self_many<S, C>(
306        &self,
307        stmt: S,
308        relation_enum: LoaderRelation<Self>,
309        db: &C,
310    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
311    where
312        C: ConnectionTrait,
313        LoaderModel<Self>: Send + Sync,
314        LoaderRelation<Self>: Send,
315        S: EntityOrSelect<LoaderEntity<Self>>,
316    {
317        LoaderTrait::load_self_many(&self.as_slice(), stmt, relation_enum, db).await
318    }
319
320    async fn load_self_via<V, C>(
321        &self,
322        via: V,
323        db: &C,
324    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
325    where
326        C: ConnectionTrait,
327        V: EntityTrait,
328        LoaderModel<Self>: Send + Sync,
329        LoaderEntity<Self>: RelatedSelfVia<V>,
330    {
331        LoaderTrait::load_self_via(&self.as_slice(), via, db).await
332    }
333
334    async fn load_self_via_rev<V, C>(
335        &self,
336        via: V,
337        db: &C,
338    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
339    where
340        C: ConnectionTrait,
341        V: EntityTrait,
342        LoaderModel<Self>: Send + Sync,
343        LoaderEntity<Self>: RelatedSelfVia<V>,
344    {
345        LoaderTrait::load_self_via_rev(&self.as_slice(), via, db).await
346    }
347
348    async fn load_one<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::Model>>, DbErr>
349    where
350        C: ConnectionTrait,
351        R: EntityTrait,
352        R::Model: Send + Sync,
353        S: EntityOrSelect<R>,
354        <Self::Model as ModelTrait>::Entity: Related<R>,
355    {
356        LoaderTrait::load_one(&self.as_slice(), stmt, db).await
357    }
358
359    async fn load_many<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::Model>>, DbErr>
360    where
361        C: ConnectionTrait,
362        R: EntityTrait,
363        R::Model: Send + Sync,
364        S: EntityOrSelect<R>,
365        <Self::Model as ModelTrait>::Entity: Related<R>,
366    {
367        LoaderTrait::load_many(&self.as_slice(), stmt, db).await
368    }
369
370    async fn load_many_to_many<R, S, V, C>(
371        &self,
372        stmt: S,
373        via: V,
374        db: &C,
375    ) -> Result<Vec<Vec<R::Model>>, DbErr>
376    where
377        C: ConnectionTrait,
378        R: EntityTrait,
379        R::Model: Send + Sync,
380        S: EntityOrSelect<R>,
381        V: EntityTrait,
382        V::Model: Send + Sync,
383        <Self::Model as ModelTrait>::Entity: Related<R>,
384    {
385        LoaderTrait::load_many_to_many(&self.as_slice(), stmt, via, db).await
386    }
387}
388
389#[async_trait::async_trait]
390impl<M> LoaderTrait for &[M]
391where
392    M: ModelTrait + Sync,
393{
394    type Model = M;
395
396    async fn load_self<S, C>(
397        &self,
398        stmt: S,
399        relation_enum: LoaderRelation<Self>,
400        db: &C,
401    ) -> Result<Vec<Option<LoaderModel<Self>>>, DbErr>
402    where
403        C: ConnectionTrait,
404        LoaderModel<Self>: Send + Sync,
405        LoaderRelation<Self>: Send,
406        S: EntityOrSelect<LoaderEntity<Self>>,
407    {
408        let rel_def = relation_enum.def();
409        check_self_ref(&rel_def)?;
410        loader_impl_impl(self.iter(), stmt.select(), rel_def, None, db).await
411    }
412
413    async fn load_self_many<S, C>(
414        &self,
415        stmt: S,
416        relation_enum: LoaderRelation<Self>,
417        db: &C,
418    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
419    where
420        C: ConnectionTrait,
421        LoaderModel<Self>: Send + Sync,
422        LoaderRelation<Self>: Send,
423        S: EntityOrSelect<LoaderEntity<Self>>,
424    {
425        let mut rel_def = relation_enum.def();
426        if rel_def.from_tbl != rel_def.to_tbl {
427            return Err(query_err("Relation must be self referencing"));
428        }
429        if !rel_def.is_owner {
430            // flip belongs_to
431            rel_def = rel_def.rev();
432        }
433        loader_impl_impl(self.iter(), stmt.select(), rel_def, None, db).await
434    }
435
436    async fn load_self_via<V, C>(&self, _: V, db: &C) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
437    where
438        C: ConnectionTrait,
439        V: EntityTrait,
440        LoaderModel<Self>: Send + Sync,
441        LoaderEntity<Self>: RelatedSelfVia<V>,
442    {
443        let rel_def = <LoaderEntity<Self> as RelatedSelfVia<V>>::to();
444        let rel_via = <LoaderEntity<Self> as RelatedSelfVia<V>>::via();
445        loader_impl_impl(
446            self.iter(),
447            EntityOrSelect::select(LoaderEntity::<Self>::default()),
448            rel_def,
449            Some(rel_via),
450            db,
451        )
452        .await
453    }
454
455    async fn load_self_via_rev<V, C>(
456        &self,
457        _: V,
458        db: &C,
459    ) -> Result<Vec<Vec<LoaderModel<Self>>>, DbErr>
460    where
461        C: ConnectionTrait,
462        V: EntityTrait,
463        LoaderModel<Self>: Send + Sync,
464        LoaderEntity<Self>: RelatedSelfVia<V>,
465    {
466        let rel_def = <LoaderEntity<Self> as RelatedSelfVia<V>>::via().rev();
467        let rel_via = <LoaderEntity<Self> as RelatedSelfVia<V>>::to().rev();
468        loader_impl_impl(
469            self.iter(),
470            EntityOrSelect::select(LoaderEntity::<Self>::default()),
471            rel_def,
472            Some(rel_via),
473            db,
474        )
475        .await
476    }
477
478    async fn load_one<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::Model>>, DbErr>
479    where
480        C: ConnectionTrait,
481        R: EntityTrait,
482        R::Model: Send + Sync,
483        S: EntityOrSelect<R>,
484        <Self::Model as ModelTrait>::Entity: Related<R>,
485    {
486        let rel_def = <<Self::Model as ModelTrait>::Entity as Related<R>>::to();
487        if rel_def.rel_type != RelationType::HasOne {
488            return Err(query_err("Relation is HasMany instead of HasOne"));
489        }
490        loader_impl(self.iter(), stmt.select(), db).await
491    }
492
493    async fn load_many<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::Model>>, DbErr>
494    where
495        C: ConnectionTrait,
496        R: EntityTrait,
497        R::Model: Send + Sync,
498        S: EntityOrSelect<R>,
499        <Self::Model as ModelTrait>::Entity: Related<R>,
500    {
501        loader_impl(self.iter(), stmt.select(), db).await
502    }
503
504    async fn load_many_to_many<R, S, V, C>(
505        &self,
506        stmt: S,
507        via: V,
508        db: &C,
509    ) -> Result<Vec<Vec<R::Model>>, DbErr>
510    where
511        C: ConnectionTrait,
512        R: EntityTrait,
513        R::Model: Send + Sync,
514        S: EntityOrSelect<R>,
515        V: EntityTrait,
516        V::Model: Send + Sync,
517        <Self::Model as ModelTrait>::Entity: Related<R>,
518    {
519        if let Some(via_rel) = <<Self::Model as ModelTrait>::Entity as Related<R>>::via() {
520            let rel_def = <<Self::Model as ModelTrait>::Entity as Related<R>>::to();
521            if rel_def.rel_type != RelationType::HasOne {
522                return Err(query_err("Relation to is not HasOne"));
523            }
524
525            if !cmp_table_ref(&via_rel.to_tbl, &via.table_ref()) {
526                return Err(query_err(format!(
527                    "The given via Entity is incorrect: expected: {:?}, given: {:?}",
528                    via_rel.to_tbl,
529                    via.table_ref()
530                )));
531            }
532
533            if self.is_empty() {
534                return Ok(Vec::new());
535            }
536
537            let pkeys = self
538                .iter()
539                .map(|model| get_key_from_model(&via_rel.from_col, model))
540                .collect::<Result<Vec<_>, _>>()?;
541
542            // Map of M::PK -> Vec<R::PK>
543            let mut keymap: HashMap<ValueTuple, Vec<ValueTuple>> = Default::default();
544
545            let keys: Vec<ValueTuple> = {
546                let condition = prepare_condition::<M>(
547                    &via_rel.to_tbl,
548                    &via_rel.from_col,
549                    &via_rel.to_col,
550                    &pkeys,
551                    db.get_database_backend(),
552                )?;
553                let stmt = V::find().filter(condition);
554                let data = stmt.all(db).await?;
555                for model in data {
556                    let pk = get_key_from_model(&via_rel.to_col, &model)?;
557                    let entry = keymap.entry(pk).or_default();
558
559                    let fk = get_key_from_model(&rel_def.from_col, &model)?;
560                    entry.push(fk);
561                }
562
563                keymap.values().flatten().cloned().collect()
564            };
565
566            let condition = prepare_condition::<V::Model>(
567                &rel_def.to_tbl,
568                &rel_def.from_col,
569                &rel_def.to_col,
570                &keys,
571                db.get_database_backend(),
572            )?;
573
574            let stmt = QueryFilter::filter(stmt.select(), condition);
575
576            let models = stmt.all(db).await?;
577
578            // Map of R::PK -> R::Model
579            let data = models.into_iter().try_fold(
580                HashMap::<ValueTuple, <R as EntityTrait>::Model>::new(),
581                |mut acc, model| {
582                    get_key_from_model(&rel_def.to_col, &model).map(|key| {
583                        acc.insert(key, model);
584
585                        acc
586                    })
587                },
588            )?;
589
590            let result: Vec<Vec<R::Model>> = pkeys
591                .into_iter()
592                .map(|pkey| {
593                    let fkeys = keymap.get(&pkey).cloned().unwrap_or_default();
594
595                    let models: Vec<_> = fkeys
596                        .into_iter()
597                        .filter_map(|fkey| data.get(&fkey).cloned())
598                        .collect();
599
600                    models
601                })
602                .collect();
603
604            Ok(result)
605        } else {
606            return Err(query_err("Relation is not ManyToMany"));
607        }
608    }
609}
610
611#[async_trait::async_trait]
612impl<M> LoaderTraitEx for &[M]
613where
614    M: ModelTrait + Sync,
615{
616    type Model = M;
617
618    async fn load_self_ex<S, C>(
619        &self,
620        stmt: S,
621        relation_enum: LoaderExRelation<Self>,
622        db: &C,
623    ) -> Result<Vec<Option<LoaderExModelEx<Self>>>, DbErr>
624    where
625        C: ConnectionTrait,
626        LoaderExModel<Self>: Send + Sync,
627        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
628        LoaderExRelation<Self>: Send,
629        S: EntityOrSelect<LoaderExEntity<Self>>,
630    {
631        let rel_def = relation_enum.def();
632        check_self_ref(&rel_def)?;
633        loader_impl_impl(self.iter(), stmt.select(), rel_def, None, db).await
634    }
635
636    async fn load_self_many_ex<S, C>(
637        &self,
638        stmt: S,
639        relation_enum: LoaderExRelation<Self>,
640        db: &C,
641    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
642    where
643        C: ConnectionTrait,
644        LoaderExModel<Self>: Send + Sync,
645        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
646        LoaderExRelation<Self>: Send,
647        S: EntityOrSelect<LoaderExEntity<Self>>,
648    {
649        let rel_def = relation_enum.def();
650        check_self_ref_many(&rel_def)?;
651        loader_impl_impl(self.iter(), stmt.select(), rel_def, None, db).await
652    }
653
654    async fn load_self_via_ex<V, C>(
655        &self,
656        _: V,
657        is_reverse: bool,
658        db: &C,
659    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
660    where
661        C: ConnectionTrait,
662        V: EntityTrait,
663        LoaderExModel<Self>: Send + Sync,
664        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
665        LoaderExEntity<Self>: RelatedSelfVia<V>,
666    {
667        let (rel_def, rel_via) = if !is_reverse {
668            (
669                <LoaderExEntity<Self> as RelatedSelfVia<V>>::to(),
670                <LoaderExEntity<Self> as RelatedSelfVia<V>>::via(),
671            )
672        } else {
673            (
674                <LoaderEntity<Self> as RelatedSelfVia<V>>::via().rev(),
675                <LoaderEntity<Self> as RelatedSelfVia<V>>::to().rev(),
676            )
677        };
678        loader_impl_impl(
679            self.iter(),
680            EntityOrSelect::select(LoaderExEntity::<Self>::default()),
681            rel_def,
682            Some(rel_via),
683            db,
684        )
685        .await
686    }
687
688    async fn load_one_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::ModelEx>>, DbErr>
689    where
690        C: ConnectionTrait,
691        R: EntityTrait,
692        R::Model: Send + Sync,
693        S: EntityOrSelect<R>,
694        R::ModelEx: From<R::Model>,
695        <Self::Model as ModelTrait>::Entity: Related<R>,
696    {
697        let rel_def = <<Self::Model as ModelTrait>::Entity as Related<R>>::to();
698        if rel_def.rel_type != RelationType::HasOne {
699            return Err(query_err("Relation is HasMany instead of HasOne"));
700        }
701        loader_impl(self.iter(), stmt.select(), db).await
702    }
703
704    async fn load_many_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::ModelEx>>, DbErr>
705    where
706        C: ConnectionTrait,
707        R: EntityTrait,
708        R::Model: Send + Sync,
709        S: EntityOrSelect<R>,
710        R::ModelEx: From<R::Model>,
711        <Self::Model as ModelTrait>::Entity: Related<R>,
712    {
713        loader_impl(self.iter(), stmt.select(), db).await
714    }
715}
716
717#[async_trait::async_trait]
718impl<M> LoaderTraitEx for &[Option<M>]
719where
720    M: ModelTrait + Sync,
721{
722    type Model = M;
723
724    async fn load_self_ex<S, C>(
725        &self,
726        stmt: S,
727        relation_enum: LoaderExRelation<Self>,
728        db: &C,
729    ) -> Result<Vec<Option<LoaderExModelEx<Self>>>, DbErr>
730    where
731        C: ConnectionTrait,
732        LoaderExModel<Self>: Send + Sync,
733        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
734        LoaderExRelation<Self>: Send,
735        S: EntityOrSelect<LoaderExEntity<Self>>,
736    {
737        let rel_def = relation_enum.def();
738        check_self_ref(&rel_def)?;
739        let items: Vec<Option<_>> = loader_impl_impl(
740            self.iter().filter_map(|o| o.as_ref()),
741            stmt.select(),
742            rel_def,
743            None,
744            db,
745        )
746        .await?;
747        Ok(assemble_options(self, items))
748    }
749
750    async fn load_self_many_ex<S, C>(
751        &self,
752        stmt: S,
753        relation_enum: LoaderExRelation<Self>,
754        db: &C,
755    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
756    where
757        C: ConnectionTrait,
758        LoaderExModel<Self>: Send + Sync,
759        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
760        LoaderExRelation<Self>: Send,
761        S: EntityOrSelect<LoaderExEntity<Self>>,
762    {
763        let rel_def = relation_enum.def();
764        check_self_ref_many(&rel_def)?;
765        let items: Vec<Vec<_>> = loader_impl_impl(
766            self.iter().filter_map(|o| o.as_ref()),
767            stmt.select(),
768            rel_def,
769            None,
770            db,
771        )
772        .await?;
773        Ok(assemble_options(self, items))
774    }
775
776    async fn load_self_via_ex<V, C>(
777        &self,
778        _: V,
779        is_reverse: bool,
780        db: &C,
781    ) -> Result<Vec<Vec<LoaderExModelEx<Self>>>, DbErr>
782    where
783        C: ConnectionTrait,
784        V: EntityTrait,
785        LoaderExModel<Self>: Send + Sync,
786        LoaderExModelEx<Self>: From<LoaderExModel<Self>>,
787        LoaderExEntity<Self>: RelatedSelfVia<V>,
788    {
789        let (rel_def, rel_via) = if !is_reverse {
790            (
791                <LoaderExEntity<Self> as RelatedSelfVia<V>>::to(),
792                <LoaderExEntity<Self> as RelatedSelfVia<V>>::via(),
793            )
794        } else {
795            (
796                <LoaderExEntity<Self> as RelatedSelfVia<V>>::via().rev(),
797                <LoaderExEntity<Self> as RelatedSelfVia<V>>::to().rev(),
798            )
799        };
800        let items: Vec<Vec<_>> = loader_impl_impl(
801            self.iter().filter_map(|o| o.as_ref()),
802            EntityOrSelect::select(LoaderExEntity::<Self>::default()),
803            rel_def,
804            Some(rel_via),
805            db,
806        )
807        .await?;
808        Ok(assemble_options(self, items))
809    }
810
811    async fn load_one_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Option<R::ModelEx>>, DbErr>
812    where
813        C: ConnectionTrait,
814        R: EntityTrait,
815        R::Model: Send + Sync,
816        S: EntityOrSelect<R>,
817        R::ModelEx: From<R::Model>,
818        <Self::Model as ModelTrait>::Entity: Related<R>,
819    {
820        let rel_def = <<Self::Model as ModelTrait>::Entity as Related<R>>::to();
821        if rel_def.rel_type != RelationType::HasOne {
822            return Err(query_err("Relation is HasMany instead of HasOne"));
823        }
824        let items: Vec<Option<R::ModelEx>> =
825            loader_impl(self.iter().filter_map(|o| o.as_ref()), stmt.select(), db).await?;
826        Ok(assemble_options(self, items))
827    }
828
829    async fn load_many_ex<R, S, C>(&self, stmt: S, db: &C) -> Result<Vec<Vec<R::ModelEx>>, DbErr>
830    where
831        C: ConnectionTrait,
832        R: EntityTrait,
833        R::Model: Send + Sync,
834        S: EntityOrSelect<R>,
835        R::ModelEx: From<R::Model>,
836        <Self::Model as ModelTrait>::Entity: Related<R>,
837    {
838        let items: Vec<Vec<R::ModelEx>> =
839            loader_impl(self.iter().filter_map(|o| o.as_ref()), stmt.select(), db).await?;
840        Ok(assemble_options(self, items))
841    }
842}
843
844#[async_trait::async_trait]
845impl<M> NestedLoaderTrait for &[Vec<M>]
846where
847    M: ModelTrait + Sync,
848{
849    type Model = M;
850
851    async fn load_self_ex<S, C>(
852        &self,
853        stmt: S,
854        relation_enum: NestedLoaderRelation<Self>,
855        db: &C,
856    ) -> Result<Vec<Vec<Option<NestedModelEx<Self>>>>, DbErr>
857    where
858        C: ConnectionTrait,
859        NestedModel<Self>: Send + Sync,
860        NestedModelEx<Self>: From<NestedModel<Self>>,
861        NestedLoaderRelation<Self>: Send,
862        S: EntityOrSelect<<<Self as NestedLoaderTrait>::Model as ModelTrait>::Entity>,
863    {
864        let rel_def = relation_enum.def();
865        check_self_ref(&rel_def)?;
866        let items: Vec<Option<_>> =
867            loader_impl_impl(self.iter().flatten(), stmt.select(), rel_def, None, db).await?;
868        Ok(assemble_vectors(self, items))
869    }
870
871    async fn load_self_many_ex<S, C>(
872        &self,
873        stmt: S,
874        relation_enum: NestedLoaderRelation<Self>,
875        db: &C,
876    ) -> Result<Vec<Vec<Vec<NestedModelEx<Self>>>>, DbErr>
877    where
878        C: ConnectionTrait,
879        NestedModel<Self>: Send + Sync,
880        NestedModelEx<Self>: From<NestedModel<Self>>,
881        NestedLoaderRelation<Self>: Send,
882        S: EntityOrSelect<<<Self as NestedLoaderTrait>::Model as ModelTrait>::Entity>,
883    {
884        let rel_def = relation_enum.def();
885        check_self_ref_many(&rel_def)?;
886        let items: Vec<Vec<_>> =
887            loader_impl_impl(self.iter().flatten(), stmt.select(), rel_def, None, db).await?;
888        Ok(assemble_vectors(self, items))
889    }
890
891    async fn load_self_via_ex<V, C>(
892        &self,
893        _: V,
894        is_reverse: bool,
895        db: &C,
896    ) -> Result<Vec<Vec<Vec<NestedModelEx<Self>>>>, DbErr>
897    where
898        C: ConnectionTrait,
899        V: EntityTrait,
900        NestedModel<Self>: Send + Sync,
901        NestedModelEx<Self>: From<NestedModel<Self>>,
902        NestedEntity<Self>: RelatedSelfVia<V>,
903    {
904        let (rel_def, rel_via) = if !is_reverse {
905            (
906                <NestedEntity<Self> as RelatedSelfVia<V>>::to(),
907                <NestedEntity<Self> as RelatedSelfVia<V>>::via(),
908            )
909        } else {
910            (
911                <NestedEntity<Self> as RelatedSelfVia<V>>::via().rev(),
912                <NestedEntity<Self> as RelatedSelfVia<V>>::to().rev(),
913            )
914        };
915        let items: Vec<Vec<_>> = loader_impl_impl(
916            self.iter().flatten(),
917            EntityOrSelect::select(NestedEntity::<Self>::default()),
918            rel_def,
919            Some(rel_via),
920            db,
921        )
922        .await?;
923        Ok(assemble_vectors(self, items))
924    }
925
926    async fn load_one_ex<R, S, C>(
927        &self,
928        stmt: S,
929        db: &C,
930    ) -> Result<Vec<Vec<Option<R::ModelEx>>>, DbErr>
931    where
932        C: ConnectionTrait,
933        R: EntityTrait,
934        R::Model: Send + Sync,
935        S: EntityOrSelect<R>,
936        R::ModelEx: From<R::Model>,
937        <Self::Model as ModelTrait>::Entity: Related<R>,
938    {
939        let rel_def = <<Self::Model as ModelTrait>::Entity as Related<R>>::to();
940        if rel_def.rel_type != RelationType::HasOne {
941            return Err(query_err("Relation is HasMany instead of HasOne"));
942        }
943        let items: Vec<Option<R::ModelEx>> =
944            loader_impl(self.iter().flatten(), stmt.select(), db).await?;
945        Ok(assemble_vectors(self, items))
946    }
947
948    async fn load_many_ex<R, S, C>(
949        &self,
950        stmt: S,
951        db: &C,
952    ) -> Result<Vec<Vec<Vec<R::ModelEx>>>, DbErr>
953    where
954        C: ConnectionTrait,
955        R: EntityTrait,
956        R::Model: Send + Sync,
957        S: EntityOrSelect<R>,
958        R::ModelEx: From<R::Model>,
959        <Self::Model as ModelTrait>::Entity: Related<R>,
960    {
961        let items: Vec<Vec<R::ModelEx>> =
962            loader_impl(self.iter().flatten(), stmt.select(), db).await?;
963        Ok(assemble_vectors(self, items))
964    }
965}
966
967fn assemble_options<I, T: Default>(input: &[Option<I>], items: Vec<T>) -> Vec<T> {
968    let mut items = items.into_iter();
969    let mut output = Vec::new();
970    for input in input.iter() {
971        if input.is_some() {
972            output.push(items.next().unwrap_or_default());
973        } else {
974            output.push(T::default());
975        }
976    }
977    output
978}
979
980fn assemble_vectors<I, T: Default>(input: &[Vec<I>], items: Vec<T>) -> Vec<Vec<T>> {
981    let mut items = items.into_iter();
982
983    let mut output = Vec::new();
984
985    for input in input.iter() {
986        output.push(Vec::new());
987
988        for _inner in input.iter() {
989            output
990                .last_mut()
991                .expect("Pushed above")
992                .push(items.next().unwrap_or_default());
993        }
994    }
995
996    output
997}
998
999trait Container: Default + Clone {
1000    type Item;
1001    fn add(&mut self, item: Self::Item);
1002}
1003
1004impl<T: Clone> Container for Vec<T> {
1005    type Item = T;
1006    fn add(&mut self, item: Self::Item) {
1007        self.push(item);
1008    }
1009}
1010
1011impl<T: Clone> Container for Option<T> {
1012    type Item = T;
1013    fn add(&mut self, item: Self::Item) {
1014        self.replace(item);
1015    }
1016}
1017
1018async fn loader_impl<'a, Model, Iter, R, C, T, Output>(
1019    items: Iter,
1020    stmt: Select<R>,
1021    db: &C,
1022) -> Result<Vec<T>, DbErr>
1023where
1024    Model: ModelTrait + Sync + 'a,
1025    Iter: Iterator<Item = &'a Model> + 'a,
1026    C: ConnectionTrait,
1027    R: EntityTrait,
1028    R::Model: Send + Sync,
1029    Model::Entity: Related<R>,
1030    Output: From<R::Model>,
1031    T: Container<Item = Output>,
1032{
1033    loader_impl_impl(
1034        items,
1035        stmt,
1036        <Model::Entity as Related<R>>::to(),
1037        <Model::Entity as Related<R>>::via(),
1038        db,
1039    )
1040    .await
1041}
1042
1043// All variants monomorphizes to this implementation, which is a constant number of variants
1044// per Entity, permutating on different shapes, e.g. Vec<Model>, Option<ModelEx>
1045async fn loader_impl_impl<'a, Model, Iter, R, C, T, Output>(
1046    items: Iter,
1047    stmt: Select<R>,
1048    rel_def: RelationDef,
1049    via_def: Option<RelationDef>,
1050    db: &C,
1051) -> Result<Vec<T>, DbErr>
1052where
1053    Model: ModelTrait + Sync + 'a,
1054    Iter: Iterator<Item = &'a Model> + 'a,
1055    C: ConnectionTrait,
1056    R: EntityTrait,
1057    R::Model: Send + Sync,
1058    Output: From<R::Model>,
1059    T: Container<Item = Output>,
1060{
1061    let (keys, hashmap) = if let Some(via_def) = via_def {
1062        let keys = items
1063            .map(|model| get_key_from_model(&via_def.from_col, model))
1064            .collect::<Result<Vec<_>, _>>()?;
1065
1066        if keys.is_empty() {
1067            return Ok(Vec::new());
1068        }
1069
1070        let condition = prepare_condition::<Model>(
1071            &via_def.to_tbl,
1072            &via_def.from_col,
1073            &via_def.to_col,
1074            &keys,
1075            db.get_database_backend(),
1076        )?;
1077
1078        let stmt = QueryFilter::filter(stmt.join_rev(JoinType::InnerJoin, rel_def), condition);
1079
1080        // The idea is to do a SelectTwo with join, then extract key via a dynamic model
1081        // i.e. select (baker + cake_baker) and extract cake_id from result rows
1082        // SELECT "baker"."id", "baker"."name", "baker"."contact_details", "baker"."bakery_id",
1083        //     "cakes_bakers"."cake_id" <- extra select
1084        // FROM "baker" <- target
1085        // INNER JOIN "cakes_bakers" <- junction
1086        //     ON "cakes_bakers"."baker_id" = "baker"."id" <- relation
1087        // WHERE "cakes_bakers"."cake_id" IN (..)
1088
1089        let data = stmt
1090            .select_also_dyn_model(
1091                via_def.to_tbl.sea_orm_table().clone(),
1092                dynamic::ModelType {
1093                    // we uses the left Model's type but the right Model's field
1094                    fields: extract_col_type::<Model>(&via_def.from_col, &via_def.to_col)?,
1095                },
1096            )
1097            .all(db)
1098            .await?;
1099
1100        let mut hashmap: HashMap<ValueTuple, T> =
1101            keys.iter()
1102                .fold(HashMap::new(), |mut acc, key: &ValueTuple| {
1103                    acc.insert(key.clone(), T::default());
1104                    acc
1105                });
1106
1107        for (item, key) in data {
1108            let key = dyn_model_to_key(key)?;
1109
1110            let vec = hashmap.get_mut(&key).ok_or_else(|| {
1111                DbErr::RecordNotFound(format!("Loader: failed to find model for {key:?}"))
1112            })?;
1113
1114            vec.add(item.into());
1115        }
1116
1117        (keys, hashmap)
1118    } else {
1119        let keys = items
1120            .map(|model| get_key_from_model(&rel_def.from_col, model))
1121            .collect::<Result<Vec<_>, _>>()?;
1122
1123        if keys.is_empty() {
1124            return Ok(Vec::new());
1125        }
1126
1127        let condition = prepare_condition::<Model>(
1128            &rel_def.to_tbl,
1129            &rel_def.from_col,
1130            &rel_def.to_col,
1131            &keys,
1132            db.get_database_backend(),
1133        )?;
1134
1135        let stmt = QueryFilter::filter(stmt, condition);
1136
1137        let data = stmt.all(db).await?;
1138
1139        let mut hashmap: HashMap<ValueTuple, T> = Default::default();
1140
1141        for item in data {
1142            let key = get_key_from_model(&rel_def.to_col, &item)?;
1143            let holder = hashmap.entry(key).or_default();
1144            holder.add(item.into());
1145        }
1146
1147        (keys, hashmap)
1148    };
1149
1150    let result: Vec<T> = keys
1151        .iter()
1152        .map(|key: &ValueTuple| hashmap.get(key).cloned().unwrap_or_default())
1153        .collect();
1154
1155    Ok(result)
1156}
1157
1158fn cmp_table_ref(left: &TableRef, right: &TableRef) -> bool {
1159    left == right
1160}
1161
1162fn extract_col_type<Model>(
1163    left: &Identity,
1164    right: &Identity,
1165) -> Result<Vec<dynamic::FieldType>, DbErr>
1166where
1167    Model: ModelTrait,
1168{
1169    use itertools::Itertools;
1170
1171    if left.arity() != right.arity() {
1172        return Err(DbErr::Type(format!(
1173            "Identity mismatch: left: {} != right: {}",
1174            left.arity(),
1175            right.arity()
1176        )));
1177    }
1178
1179    let vec = left
1180        .iter()
1181        .zip_eq(right.iter())
1182        .map(|(l, r)| {
1183            let col_a =
1184                <<<Model as ModelTrait>::Entity as EntityTrait>::Column as FromStr>::from_str(
1185                    &l.inner(),
1186                )
1187                .map_err(|_| DbErr::Type(format!("Failed at mapping '{l}'")))?;
1188            Ok(dynamic::FieldType::new(
1189                r.clone(),
1190                Model::get_value_type(col_a),
1191            ))
1192        })
1193        .collect::<Result<Vec<_>, DbErr>>()?;
1194
1195    Ok(vec)
1196}
1197
1198#[allow(clippy::unwrap_used)]
1199fn dyn_model_to_key(dyn_model: dynamic::Model) -> Result<ValueTuple, DbErr> {
1200    Ok(match dyn_model.fields.len() {
1201        0 => return Err(DbErr::Type("Identity zero?".into())),
1202        1 => ValueTuple::One(dyn_model.fields.into_iter().next().unwrap().value),
1203        2 => {
1204            let mut iter = dyn_model.fields.into_iter();
1205            ValueTuple::Two(iter.next().unwrap().value, iter.next().unwrap().value)
1206        }
1207        3 => {
1208            let mut iter = dyn_model.fields.into_iter();
1209            ValueTuple::Three(
1210                iter.next().unwrap().value,
1211                iter.next().unwrap().value,
1212                iter.next().unwrap().value,
1213            )
1214        }
1215        _ => ValueTuple::Many(dyn_model.fields.into_iter().map(|v| v.value).collect()),
1216    })
1217}
1218
1219fn arity_mismatch(expected: usize, actual: &ValueTuple) -> DbErr {
1220    DbErr::Type(format!(
1221        "Loader: arity mismatch: expected {expected}, got {} in {actual:?}",
1222        actual.arity()
1223    ))
1224}
1225
1226fn prepare_condition<Model>(
1227    table: &TableRef,
1228    from: &Identity,
1229    to: &Identity,
1230    keys: &[ValueTuple],
1231    db_backend: DbBackend,
1232) -> Result<Condition, DbErr>
1233where
1234    Model: ModelTrait,
1235{
1236    if matches!(db_backend, DbBackend::Postgres) {
1237        prepare_condition_with_save_as::<Model>(table, from, to, keys)
1238    } else {
1239        column_tuple_in_condition(table, to, keys, db_backend)
1240    }
1241}
1242
1243fn prepare_condition_with_save_as<Model>(
1244    table: &TableRef,
1245    from: &Identity,
1246    to: &Identity,
1247    keys: &[ValueTuple],
1248) -> Result<Condition, DbErr>
1249where
1250    Model: ModelTrait,
1251{
1252    use itertools::Itertools;
1253
1254    let keys = keys.iter().unique();
1255    let (from_cols, to_cols) = resolve_column_pairs::<Model>(table, from, to)?;
1256
1257    if from_cols.is_empty() || to_cols.is_empty() {
1258        return Err(DbErr::Type(format!(
1259            "Loader: resolved zero columns for identities {from:?} -> {to:?}"
1260        )));
1261    }
1262
1263    let arity = from_cols.len();
1264
1265    let value_tuples = keys
1266        .map(|key| {
1267            let key_arity = key.arity();
1268            if arity != key_arity {
1269                return Err(arity_mismatch(arity, key));
1270            }
1271
1272            // For Postgres, we need to use `AS` to cast the value to the correct type
1273            Ok(apply_save_as::<Model>(&from_cols, key.clone()))
1274        })
1275        .collect::<Result<Vec<_>, DbErr>>()?;
1276
1277    // Build `(c1, c2, ...) IN ((v11, v12, ...), (v21, v22, ...), ...)`
1278    let expr = Expr::tuple(create_table_columns(table, to)).is_in(value_tuples);
1279
1280    Ok(expr.into())
1281}
1282
1283type ModelColumn<M> = <<M as ModelTrait>::Entity as EntityTrait>::Column;
1284
1285type ColumnPairs<M> = (Vec<ModelColumn<M>>, Vec<ColumnRef>);
1286
1287fn resolve_column_pairs<Model>(
1288    table: &TableRef,
1289    from: &Identity,
1290    to: &Identity,
1291) -> Result<ColumnPairs<Model>, DbErr>
1292where
1293    Model: ModelTrait,
1294    ModelColumn<Model>: ColumnTrait,
1295{
1296    let from_columns = parse_identity_columns::<Model>(from)?;
1297    let to_columns = column_refs_from_identity(table, to);
1298
1299    if from_columns.len() != to_columns.len() {
1300        return Err(DbErr::Type(format!(
1301            "Loader: identity column count mismatch between {from:?} and {to:?}"
1302        )));
1303    }
1304
1305    Ok((from_columns, to_columns))
1306}
1307
1308fn check_self_ref(rel_def: &RelationDef) -> Result<(), DbErr> {
1309    if rel_def.from_tbl != rel_def.to_tbl {
1310        return Err(query_err("Relation must be self referencing"));
1311    }
1312    if rel_def.is_owner {
1313        return Err(query_err("Relation must be belongs_to"));
1314    }
1315    Ok(())
1316}
1317
1318fn check_self_ref_many(rel_def: &RelationDef) -> Result<(), DbErr> {
1319    if rel_def.from_tbl != rel_def.to_tbl {
1320        return Err(query_err("Relation must be self referencing"));
1321    }
1322    if !rel_def.is_owner {
1323        return Err(query_err("Relation must not be belongs_to"));
1324    }
1325    Ok(())
1326}
1327
1328fn column_refs_from_identity(table: &TableRef, identity: &Identity) -> Vec<ColumnRef> {
1329    identity
1330        .iter()
1331        .map(|col| table_column(table, col))
1332        .collect()
1333}
1334
1335fn parse_identity_columns<Model>(identity: &Identity) -> Result<Vec<ModelColumn<Model>>, DbErr>
1336where
1337    Model: ModelTrait,
1338{
1339    identity
1340        .iter()
1341        .map(|from_col| try_conv_ident_to_column::<Model>(from_col))
1342        .collect()
1343}
1344
1345fn try_conv_ident_to_column<Model>(ident: &DynIden) -> Result<ModelColumn<Model>, DbErr>
1346where
1347    Model: ModelTrait,
1348{
1349    let column_name = ident.inner();
1350    ModelColumn::<Model>::from_str(&column_name)
1351        .map_err(|_| DbErr::Type(format!("Failed at mapping '{column_name}' to column")))
1352}
1353
1354fn table_column(tbl: &TableRef, col: &DynIden) -> ColumnRef {
1355    (tbl.sea_orm_table().to_owned(), col.clone()).into_column_ref()
1356}
1357
1358/// Create a vector of `Expr::col` from the table and identity, e.g. [Expr::col((table, col1)), Expr::col((table, col2)), ...]
1359fn create_table_columns(table: &TableRef, cols: &Identity) -> Vec<Expr> {
1360    cols.iter()
1361        .map(|col| table_column(table, col))
1362        .map(Expr::col)
1363        .collect()
1364}
1365
1366/// Apply `save_as` to each value in the tuple, e.g. `(Cast(val1 as type1), Cast(val2 as type2), ...)`
1367fn apply_save_as<M: ModelTrait>(cols: &[ModelColumn<M>], values: ValueTuple) -> Expr {
1368    let values_expr_iter = values.into_iter().map(Expr::val);
1369
1370    let tuple_exprs: Vec<_> = cols
1371        .iter()
1372        .zip(values_expr_iter)
1373        .map(|(model_column, value)| model_column.save_as(value))
1374        .collect();
1375
1376    Expr::tuple(tuple_exprs)
1377}
1378
1379#[cfg(test)]
1380mod tests {
1381    fn cake_model(id: i32) -> sea_orm::tests_cfg::cake::Model {
1382        let name = match id {
1383            1 => "apple cake",
1384            2 => "orange cake",
1385            3 => "fruit cake",
1386            4 => "chocolate cake",
1387            _ => "",
1388        }
1389        .to_string();
1390        sea_orm::tests_cfg::cake::Model { id, name }
1391    }
1392
1393    fn fruit_model(id: i32, cake_id: Option<i32>) -> sea_orm::tests_cfg::fruit::Model {
1394        let name = match id {
1395            1 => "apple",
1396            2 => "orange",
1397            3 => "grape",
1398            4 => "strawberry",
1399            _ => "",
1400        }
1401        .to_string();
1402        sea_orm::tests_cfg::fruit::Model { id, name, cake_id }
1403    }
1404
1405    fn filling_model(id: i32) -> sea_orm::tests_cfg::filling::Model {
1406        let name = match id {
1407            1 => "apple juice",
1408            2 => "orange jam",
1409            3 => "chocolate crust",
1410            4 => "strawberry jam",
1411            _ => "",
1412        }
1413        .to_string();
1414        sea_orm::tests_cfg::filling::Model {
1415            id,
1416            name,
1417            vendor_id: Some(1),
1418            ignored_attr: 0,
1419        }
1420    }
1421
1422    fn cake_filling_model(
1423        cake_id: i32,
1424        filling_id: i32,
1425    ) -> sea_orm::tests_cfg::cake_filling::Model {
1426        sea_orm::tests_cfg::cake_filling::Model {
1427            cake_id,
1428            filling_id,
1429        }
1430    }
1431
1432    #[tokio::test]
1433    async fn test_load_one() {
1434        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1435
1436        let db = MockDatabase::new(DbBackend::Postgres)
1437            .append_query_results([[cake_model(1), cake_model(2)]])
1438            .into_connection();
1439
1440        let fruits = vec![fruit_model(1, Some(1))];
1441
1442        let cakes = fruits
1443            .load_one(cake::Entity::find(), &db)
1444            .await
1445            .expect("Should return something");
1446
1447        assert_eq!(cakes, [Some(cake_model(1))]);
1448    }
1449
1450    #[tokio::test]
1451    async fn test_load_one_same_cake() {
1452        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1453
1454        let db = MockDatabase::new(DbBackend::Postgres)
1455            .append_query_results([[cake_model(1), cake_model(2)]])
1456            .into_connection();
1457
1458        let fruits = vec![fruit_model(1, Some(1)), fruit_model(2, Some(1))];
1459
1460        let cakes = fruits
1461            .load_one(cake::Entity::find(), &db)
1462            .await
1463            .expect("Should return something");
1464
1465        assert_eq!(cakes, [Some(cake_model(1)), Some(cake_model(1))]);
1466    }
1467
1468    #[tokio::test]
1469    async fn test_load_one_empty() {
1470        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1471
1472        let db = MockDatabase::new(DbBackend::Postgres)
1473            .append_query_results([[cake_model(1), cake_model(2)]])
1474            .into_connection();
1475
1476        let fruits: Vec<fruit::Model> = vec![];
1477
1478        let cakes = fruits
1479            .load_one(cake::Entity::find(), &db)
1480            .await
1481            .expect("Should return something");
1482
1483        assert_eq!(cakes, []);
1484    }
1485
1486    #[tokio::test]
1487    async fn test_load_many() {
1488        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1489
1490        let db = MockDatabase::new(DbBackend::Postgres)
1491            .append_query_results([[fruit_model(1, Some(1))]])
1492            .into_connection();
1493
1494        let cakes = vec![cake_model(1), cake_model(2)];
1495
1496        let fruits = cakes
1497            .load_many(fruit::Entity::find(), &db)
1498            .await
1499            .expect("Should return something");
1500
1501        assert_eq!(fruits, [vec![fruit_model(1, Some(1))], vec![]]);
1502    }
1503
1504    #[tokio::test]
1505    async fn test_load_many_same_fruit() {
1506        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1507
1508        let db = MockDatabase::new(DbBackend::Postgres)
1509            .append_query_results([[fruit_model(1, Some(1)), fruit_model(2, Some(1))]])
1510            .into_connection();
1511
1512        let cakes = vec![cake_model(1), cake_model(2)];
1513
1514        let fruits = cakes
1515            .load_many(fruit::Entity::find(), &db)
1516            .await
1517            .expect("Should return something");
1518
1519        assert_eq!(
1520            fruits,
1521            [
1522                vec![fruit_model(1, Some(1)), fruit_model(2, Some(1))],
1523                vec![]
1524            ]
1525        );
1526    }
1527
1528    #[tokio::test]
1529    async fn test_load_many_empty() {
1530        use sea_orm::{DbBackend, MockDatabase, entity::prelude::*, tests_cfg::*};
1531
1532        let db = MockDatabase::new(DbBackend::Postgres).into_connection();
1533
1534        let cakes: Vec<cake::Model> = vec![];
1535
1536        let fruits = cakes
1537            .load_many(fruit::Entity::find(), &db)
1538            .await
1539            .expect("Should return something");
1540
1541        let empty_vec: Vec<Vec<fruit::Model>> = vec![];
1542
1543        assert_eq!(fruits, empty_vec);
1544    }
1545
1546    #[tokio::test]
1547    async fn test_load_many_to_many_base() {
1548        use sea_orm::{DbBackend, IntoMockRow, LoaderTrait, MockDatabase, tests_cfg::*};
1549
1550        let db = MockDatabase::new(DbBackend::Postgres)
1551            .append_query_results([
1552                [cake_filling_model(1, 1).into_mock_row()],
1553                [filling_model(1).into_mock_row()],
1554            ])
1555            .into_connection();
1556
1557        let cakes = vec![cake_model(1)];
1558
1559        let fillings = cakes
1560            .load_many_to_many(Filling, CakeFilling, &db)
1561            .await
1562            .expect("Should return something");
1563
1564        assert_eq!(fillings, vec![vec![filling_model(1)]]);
1565    }
1566
1567    #[tokio::test]
1568    async fn test_load_many_to_many_complex() {
1569        use sea_orm::{DbBackend, IntoMockRow, LoaderTrait, MockDatabase, tests_cfg::*};
1570
1571        let db = MockDatabase::new(DbBackend::Postgres)
1572            .append_query_results([
1573                [
1574                    cake_filling_model(1, 1).into_mock_row(),
1575                    cake_filling_model(1, 2).into_mock_row(),
1576                    cake_filling_model(1, 3).into_mock_row(),
1577                    cake_filling_model(2, 1).into_mock_row(),
1578                    cake_filling_model(2, 2).into_mock_row(),
1579                ],
1580                [
1581                    filling_model(1).into_mock_row(),
1582                    filling_model(2).into_mock_row(),
1583                    filling_model(3).into_mock_row(),
1584                    filling_model(4).into_mock_row(),
1585                    filling_model(5).into_mock_row(),
1586                ],
1587            ])
1588            .into_connection();
1589
1590        let cakes = vec![cake_model(1), cake_model(2), cake_model(3)];
1591
1592        let fillings = cakes
1593            .load_many_to_many(Filling, CakeFilling, &db)
1594            .await
1595            .expect("Should return something");
1596
1597        assert_eq!(
1598            fillings,
1599            vec![
1600                vec![filling_model(1), filling_model(2), filling_model(3)],
1601                vec![filling_model(1), filling_model(2)],
1602                vec![],
1603            ]
1604        );
1605    }
1606
1607    #[tokio::test]
1608    async fn test_load_many_to_many_empty() {
1609        use sea_orm::{DbBackend, IntoMockRow, LoaderTrait, MockDatabase, tests_cfg::*};
1610
1611        let db = MockDatabase::new(DbBackend::Postgres)
1612            .append_query_results([
1613                [cake_filling_model(1, 1).into_mock_row()],
1614                [filling_model(1).into_mock_row()],
1615            ])
1616            .into_connection();
1617
1618        let cakes: Vec<cake::Model> = vec![];
1619
1620        let fillings = cakes
1621            .load_many_to_many(Filling, CakeFilling, &db)
1622            .await
1623            .expect("Should return something");
1624
1625        let empty_vec: Vec<Vec<filling::Model>> = vec![];
1626
1627        assert_eq!(fillings, empty_vec);
1628    }
1629
1630    #[tokio::test]
1631    async fn test_load_one_duplicate_keys() {
1632        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1633
1634        let db = MockDatabase::new(DbBackend::Postgres)
1635            .append_query_results([[cake_model(1), cake_model(2)]])
1636            .into_connection();
1637
1638        let fruits = vec![
1639            fruit_model(1, Some(1)),
1640            fruit_model(2, Some(1)),
1641            fruit_model(3, Some(1)),
1642            fruit_model(4, Some(1)),
1643        ];
1644
1645        let cakes = fruits
1646            .load_one(cake::Entity::find(), &db)
1647            .await
1648            .expect("Should return something");
1649
1650        assert_eq!(cakes.len(), 4);
1651        for cake in &cakes {
1652            assert_eq!(cake, &Some(cake_model(1)));
1653        }
1654        let logs = db.into_transaction_log();
1655        let sql = format!("{:?}", logs[0]);
1656
1657        let values_count = sql.matches("$1").count();
1658        assert_eq!(values_count, 1, "Duplicate values were not removed");
1659    }
1660
1661    #[tokio::test]
1662    async fn test_load_many_duplicate_keys() {
1663        use sea_orm::{DbBackend, LoaderTrait, MockDatabase, entity::prelude::*, tests_cfg::*};
1664
1665        let db = MockDatabase::new(DbBackend::Postgres)
1666            .append_query_results([[
1667                fruit_model(1, Some(1)),
1668                fruit_model(2, Some(1)),
1669                fruit_model(3, Some(2)),
1670            ]])
1671            .into_connection();
1672
1673        let cakes = vec![cake_model(1), cake_model(1), cake_model(2), cake_model(2)];
1674
1675        let fruits = cakes
1676            .load_many(fruit::Entity::find(), &db)
1677            .await
1678            .expect("Should return something");
1679
1680        assert_eq!(fruits.len(), 4);
1681
1682        let logs = db.into_transaction_log();
1683        let sql = format!("{:?}", logs[0]);
1684
1685        let values_count = sql.matches("$1").count() + sql.matches("$2").count();
1686        assert_eq!(values_count, 2, "Duplicate values were not removed");
1687    }
1688
1689    #[test]
1690    fn test_assemble_vectors() {
1691        use super::assemble_vectors;
1692
1693        assert_eq!(
1694            assemble_vectors(&[vec![1], vec![], vec![2, 3], vec![]], vec![11, 22, 33]),
1695            [vec![11], vec![], vec![22, 33], vec![]]
1696        );
1697    }
1698}