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