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
10pub trait EntityOrSelect<E: EntityTrait>: Send {
14 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#[async_trait::async_trait]
25pub trait LoaderTrait {
26 type Model: ModelTrait;
28
29 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 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 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 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 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 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 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 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 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 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
1043async 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 let data = stmt
1090 .select_also_dyn_model(
1091 via_def.to_tbl.sea_orm_table().clone(),
1092 dynamic::ModelType {
1093 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 Ok(apply_save_as::<Model>(&from_cols, key.clone()))
1274 })
1275 .collect::<Result<Vec<_>, DbErr>>()?;
1276
1277 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
1358fn 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
1366fn 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}