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