1use super::{ActiveValue, ActiveValue::*};
2use crate::{
3 ColumnTrait, Condition, ConnectionTrait, DbBackend, DeleteResult, EntityName, EntityTrait,
4 IdenStatic, Iterable, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter,
5 Related, RelatedSelfVia, RelationDef, RelationTrait, Value,
6 error::*,
7 query::{
8 clear_key_on_active_model, column_tuple_in_condition, get_key_from_active_model,
9 set_key_on_active_model,
10 },
11};
12use sea_query::ValueTuple;
13use std::fmt::Debug;
14
15pub trait ActiveModelTrait: Clone + Debug {
27 type Entity: EntityTrait;
29
30 fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
32
33 fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
35
36 fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
38 self.try_set(c, v)
39 .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
40 }
41
42 fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
44
45 fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
47
48 fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
50
51 fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
53
54 fn default() -> Self;
56
57 fn default_values() -> Self;
59
60 fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
63
64 fn reset_all(mut self) -> Self {
67 for col in <Self::Entity as EntityTrait>::Column::iter() {
68 self.reset(col);
69 }
70 self
71 }
72
73 fn get_primary_key_value(&self) -> Option<ValueTuple> {
75 let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
76 macro_rules! next {
77 () => {
78 self.get(cols.next()?.into_column()).into_value()?
79 };
80 }
81 match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
82 1 => {
83 let s1 = next!();
84 Some(ValueTuple::One(s1))
85 }
86 2 => {
87 let s1 = next!();
88 let s2 = next!();
89 Some(ValueTuple::Two(s1, s2))
90 }
91 3 => {
92 let s1 = next!();
93 let s2 = next!();
94 let s3 = next!();
95 Some(ValueTuple::Three(s1, s2, s3))
96 }
97 len => {
98 let mut vec = Vec::with_capacity(len);
99 for _ in 0..len {
100 let s = next!();
101 vec.push(s);
102 }
103 Some(ValueTuple::Many(vec))
104 }
105 }
106 }
107
108 fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
213 where
214 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
215 Self: ActiveModelBehavior,
216 C: ConnectionTrait,
217 {
218 let am = ActiveModelBehavior::before_save(self, db, true)?;
219 let model = <Self::Entity as EntityTrait>::insert(am).exec_with_returning(db)?;
220 Self::after_save(model, db, true)
221 }
222
223 fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
331 where
332 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
333 Self: ActiveModelBehavior,
334 C: ConnectionTrait,
335 {
336 let am = ActiveModelBehavior::before_save(self, db, false)?;
337 let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db)?;
338 Self::after_save(model, db, false)
339 }
340
341 fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
344 where
345 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
346 Self: ActiveModelBehavior,
347 C: ConnectionTrait,
348 {
349 let res = if !self.is_update() {
350 self.insert(db)
351 } else {
352 self.update(db)
353 }?;
354 Ok(res.into_active_model())
355 }
356
357 #[doc(hidden)]
359 fn is_update(&self) -> bool {
360 let mut is_update = true;
361 for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
362 let col = key.into_column();
363 if self.is_not_set(col) {
364 is_update = false;
365 break;
366 }
367 }
368 is_update
369 }
370
371 fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
414 where
415 Self: ActiveModelBehavior,
416 C: ConnectionTrait,
417 {
418 let am = ActiveModelBehavior::before_delete(self, db)?;
419 let am_clone = am.clone();
420 let delete_res = Self::Entity::delete(am).exec(db)?;
421 ActiveModelBehavior::after_delete(am_clone, db)?;
422 Ok(delete_res)
423 }
424
425 #[cfg(feature = "with-json")]
429 fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
430 where
431 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
432 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
433 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
434 serde::de::Deserialize<'de> + serde::Serialize,
435 {
436 use crate::Iterable;
437
438 let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
440 <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
441 .map(|pk| (pk.into_column(), self.take(pk.into_column())))
442 .collect();
443
444 *self = Self::from_json(json)?;
446
447 for (col, active_value) in primary_key_values {
449 match active_value {
450 ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
451 NotSet => self.not_set(col),
452 }
453 }
454
455 Ok(())
456 }
457
458 #[cfg(feature = "with-json")]
460 fn from_json(mut json: serde_json::Value) -> Result<Self, DbErr>
461 where
462 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
463 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
464 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
465 serde::de::Deserialize<'de> + serde::Serialize,
466 {
467 use crate::{IdenStatic, Iterable};
468
469 let serde_json::Value::Object(obj) = &json else {
470 return Err(DbErr::Json(format!(
471 "invalid type: expected JSON object for {}",
472 <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
473 )));
474 };
475
476 let mut json_keys: Vec<(<Self::Entity as EntityTrait>::Column, bool)> = Vec::new();
478
479 for col in <<Self::Entity as EntityTrait>::Column>::iter() {
480 let key = col.json_key();
481 let has_key = obj.contains_key(key);
482 json_keys.push((col, has_key));
483 }
484
485 let dummy_model = Self::default_values();
487 if let Ok(dummy_model) = dummy_model.try_into_model() {
488 if let Ok(mut dummy_json) = serde_json::to_value(&dummy_model) {
489 let serde_json::Value::Object(merged) = &mut dummy_json else {
490 unreachable!();
491 };
492 let serde_json::Value::Object(obj) = json else {
493 unreachable!();
494 };
495 for (key, value) in obj {
497 merged.insert(key, value);
498 }
499 json = dummy_json;
500 }
501 }
502
503 let model: <Self::Entity as EntityTrait>::Model =
505 serde_json::from_value(json).map_err(json_err)?;
506 let mut am = model.into_active_model();
507
508 for (col, json_key_exists) in json_keys {
510 match (json_key_exists, am.get(col)) {
511 (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
512 am.set(col, value);
513 }
514 _ => {
515 am.not_set(col);
516 }
517 }
518 }
519
520 Ok(am)
521 }
522
523 #[cfg(feature = "with-arrow")]
538 fn from_arrow(batch: &sea_orm_arrow::arrow::array::RecordBatch) -> Result<Vec<Self>, DbErr> {
539 use crate::{IdenStatic, Iterable, with_arrow::arrow_array_to_value};
540
541 let num_rows = batch.num_rows();
542 let mut results = Vec::with_capacity(num_rows);
543
544 for row in 0..num_rows {
545 let mut am = Self::default();
546
547 for col in <<Self::Entity as EntityTrait>::Column>::iter() {
548 let col_name = col.as_str();
549
550 if let Some(arrow_col) = batch.column_by_name(col_name) {
551 let col_def = col.def();
552 let col_type = col_def.get_column_type();
553 let value = arrow_array_to_value(arrow_col.as_ref(), col_type, row)?;
554
555 #[cfg(all(feature = "with-chrono", feature = "with-time"))]
560 {
561 use crate::with_arrow::{arrow_array_to_value_alt, is_datetime_column};
562 match am.try_set(col, value) {
563 Ok(()) => {}
564 Err(first_err) if is_datetime_column(col_type) => {
565 if let Some(alt_value) =
566 arrow_array_to_value_alt(arrow_col.as_ref(), col_type, row)?
567 {
568 am.try_set(col, alt_value)?;
569 } else {
570 return Err(first_err);
571 }
572 }
573 Err(e) => return Err(e),
574 }
575 }
576
577 #[cfg(not(all(feature = "with-chrono", feature = "with-time")))]
578 am.try_set(col, value)?;
579 } else {
580 am.not_set(col);
581 }
582 }
583
584 results.push(am);
585 }
586
587 Ok(results)
588 }
589
590 #[cfg(feature = "with-arrow")]
603 fn to_arrow(
604 models: &[Self],
605 schema: &sea_orm_arrow::arrow::datatypes::Schema,
606 ) -> Result<sea_orm_arrow::arrow::array::RecordBatch, DbErr> {
607 use crate::{Iterable, with_arrow::option_values_to_arrow_array};
608 use std::sync::Arc;
609
610 let mut columns: Vec<Arc<dyn sea_orm_arrow::arrow::array::Array>> =
611 Vec::with_capacity(schema.fields().len());
612
613 for field in schema.fields() {
614 let field_name = field.name();
615
616 let entity_col =
618 <<Self::Entity as EntityTrait>::Column>::iter().find(|c| c.as_str() == field_name);
619
620 if let Some(col) = entity_col {
621 let values: Vec<Option<Value>> = models
622 .iter()
623 .map(|m| match m.get(col) {
624 ActiveValue::Set(v) | ActiveValue::Unchanged(v) => Some(v),
625 ActiveValue::NotSet => None,
626 })
627 .collect();
628
629 let array = option_values_to_arrow_array(&values, field.data_type())?;
630 columns.push(array);
631 } else {
632 let array =
634 sea_orm_arrow::arrow::array::new_null_array(field.data_type(), models.len());
635 columns.push(array);
636 }
637 }
638
639 sea_orm_arrow::arrow::array::RecordBatch::try_new(Arc::new(schema.clone()), columns)
640 .map_err(|e| DbErr::Type(format!("Failed to create RecordBatch: {e}")))
641 }
642
643 fn is_changed(&self) -> bool {
645 <Self::Entity as EntityTrait>::Column::iter()
646 .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
647 }
648
649 #[doc(hidden)]
650 fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
652 where
653 R: EntityTrait,
654 AM: ActiveModelTrait<Entity = R>,
655 Self::Entity: Related<R>,
656 {
657 let rel_def = Self::Entity::to();
658
659 if rel_def.is_owner {
660 return Err(DbErr::Type(format!(
661 "Relation from {} to {} is not belongs_to",
662 <Self::Entity as Default>::default().as_str(),
663 <R as Default>::default().as_str()
664 )));
665 }
666
667 let values = get_key_from_active_model(&rel_def.to_col, model)?;
668
669 set_key_on_active_model(&rel_def.from_col, self, values)?;
670
671 Ok(())
672 }
673
674 #[doc(hidden)]
675 fn set_parent_key_for<R, AM>(
676 &mut self,
677 model: &AM,
678 rel: <Self::Entity as EntityTrait>::Relation,
679 ) -> Result<(), DbErr>
680 where
681 R: EntityTrait,
682 AM: ActiveModelTrait<Entity = R>,
683 {
684 let rel_def = rel.def();
685
686 if rel_def.is_owner {
687 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
688 }
689
690 let values = get_key_from_active_model(&rel_def.to_col, model)?;
691
692 set_key_on_active_model(&rel_def.from_col, self, values)?;
693
694 Ok(())
695 }
696
697 #[doc(hidden)]
698 fn set_parent_key_for_def<R, AM>(
699 &mut self,
700 model: &AM,
701 rel_def: &RelationDef,
702 ) -> Result<(), DbErr>
703 where
704 R: EntityTrait,
705 AM: ActiveModelTrait<Entity = R>,
706 {
707 if rel_def.is_owner {
708 return Err(DbErr::Type(format!(
709 "Relation {rel_def:?} is not belongs_to"
710 )));
711 }
712
713 let values = get_key_from_active_model(&rel_def.to_col, model)?;
714
715 set_key_on_active_model(&rel_def.from_col, self, values)?;
716
717 Ok(())
718 }
719
720 #[doc(hidden)]
721 fn set_parent_key_for_self_rev<AM>(
722 &mut self,
723 model: &AM,
724 rel: <Self::Entity as EntityTrait>::Relation,
725 ) -> Result<(), DbErr>
726 where
727 AM: ActiveModelTrait<Entity = Self::Entity>,
728 {
729 let rel_def = rel.def();
730
731 if !rel_def.is_owner {
732 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
733 }
734
735 let values = get_key_from_active_model(&rel_def.from_col, model)?;
736
737 set_key_on_active_model(&rel_def.to_col, self, values)?;
738
739 Ok(())
740 }
741
742 #[doc(hidden)]
743 fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
745 where
746 R: EntityTrait,
747 Self::Entity: Related<R>,
748 {
749 let rel_def = Self::Entity::to();
750
751 if rel_def.is_owner {
752 return Err(DbErr::Type(format!(
753 "Relation from {} to {} is not belongs_to",
754 <Self::Entity as Default>::default().as_str(),
755 <R as Default>::default().as_str()
756 )));
757 }
758
759 clear_key_on_active_model(&rel_def.from_col, self)
760 }
761
762 #[doc(hidden)]
763 fn clear_parent_key_for_self_rev(
764 &mut self,
765 rel: <Self::Entity as EntityTrait>::Relation,
766 ) -> Result<bool, DbErr> {
767 let rel_def = rel.def();
768
769 if !rel_def.is_owner {
770 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
771 }
772
773 clear_key_on_active_model(&rel_def.to_col, self)
774 }
775
776 #[doc(hidden)]
777 fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
779 where
780 R: EntityTrait,
781 Self::Entity: Related<R>,
782 {
783 let rel_def = Self::Entity::to();
784
785 if rel_def.is_owner {
786 return Err(DbErr::Type(format!(
787 "Relation from {} to {} is not belongs_to",
788 <Self::Entity as Default>::default().as_str(),
789 <R as Default>::default().as_str()
790 )));
791 }
792
793 get_key_from_active_model(&rel_def.from_col, self)
794 }
795
796 #[doc(hidden)]
797 fn get_parent_key_for(
799 &self,
800 rel: <Self::Entity as EntityTrait>::Relation,
801 ) -> Result<ValueTuple, DbErr> {
802 let rel_def = rel.def();
803
804 if rel_def.is_owner {
805 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
806 }
807
808 get_key_from_active_model(&rel_def.from_col, self)
809 }
810
811 #[doc(hidden)]
812 fn find_belongs_to_self(
813 &self,
814 rel: <Self::Entity as EntityTrait>::Relation,
815 db_backend: DbBackend,
816 ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
817 let rel_def = rel.def();
818
819 if !rel_def.is_owner {
820 return Err(DbErr::Type(format!(
821 "Relation {rel:?} is not has_one / has_many"
822 )));
823 }
824
825 let id = get_key_from_active_model(&rel_def.from_col, self)?;
826
827 Ok(Self::Entity::find().filter(
828 column_tuple_in_condition(
829 &<Self::Entity as Default>::default().table_ref(),
830 &rel_def.to_col,
831 &[id],
832 db_backend,
833 )
834 .expect(""),
835 ))
836 }
837
838 #[doc(hidden)]
839 fn find_belongs_to_model<AM>(
840 rel_def: &RelationDef,
841 belongs_to: &AM,
842 db_backend: DbBackend,
843 ) -> Result<crate::query::Select<Self::Entity>, DbErr>
844 where
845 AM: ActiveModelTrait,
846 {
847 if rel_def.is_owner {
848 return Err(DbErr::Type(format!(
849 "Relation {rel_def:?} is not belongs_to"
850 )));
851 }
852
853 let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
854 Ok(<Self::Entity as EntityTrait>::find().filter(
855 column_tuple_in_condition(&rel_def.from_tbl, &rel_def.from_col, &[id], db_backend)
856 .expect(""),
857 ))
858 }
859
860 fn find_related<R>(&self, _: R) -> crate::query::Select<R>
862 where
863 R: EntityTrait,
864 Self::Entity: Related<R>,
865 {
866 Self::Entity::find_related().belongs_to_active_model(self)
867 }
868
869 #[doc(hidden)]
871 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
872 where
873 AM: ActiveModelTrait,
874 Self::Entity: Related<AM::Entity>,
875 {
876 self.find_related(AM::Entity::default())
877 }
878
879 #[doc(hidden)]
882 fn establish_links<J, R, RM, C>(
883 &self,
884 _: J,
885 related_models: &[RM],
886 delete_leftover: bool,
887 db: &C,
888 ) -> Result<(), DbErr>
889 where
890 R: EntityTrait,
891 RM: ActiveModelTrait<Entity = R>,
892 J: EntityTrait + Related<R> + Related<Self::Entity>,
893 J::Model: IntoActiveModel<J::ActiveModel>,
894 J::ActiveModel: ActiveModelBehavior,
895 C: ConnectionTrait,
896 {
897 let left = <J as Related<Self::Entity>>::to();
898 let right = <J as Related<R>>::to();
899
900 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
901 }
902
903 #[doc(hidden)]
905 fn establish_links_self<J, RM, C>(
906 &self,
907 _: J,
908 related_models: &[RM],
909 delete_leftover: bool,
910 db: &C,
911 ) -> Result<(), DbErr>
912 where
913 RM: ActiveModelTrait<Entity = Self::Entity>,
914 J: EntityTrait,
915 J::Model: IntoActiveModel<J::ActiveModel>,
916 J::ActiveModel: ActiveModelBehavior,
917 C: ConnectionTrait,
918 Self::Entity: RelatedSelfVia<J>,
919 {
920 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
921 let right = <Self::Entity as RelatedSelfVia<J>>::to();
922
923 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
924 }
925
926 #[doc(hidden)]
928 fn establish_links_self_rev<J, RM, C>(
929 &self,
930 _: J,
931 related_models: &[RM],
932 delete_leftover: bool,
933 db: &C,
934 ) -> Result<(), DbErr>
935 where
936 RM: ActiveModelTrait<Entity = Self::Entity>,
937 J: EntityTrait,
938 J::Model: IntoActiveModel<J::ActiveModel>,
939 J::ActiveModel: ActiveModelBehavior,
940 C: ConnectionTrait,
941 Self::Entity: RelatedSelfVia<J>,
942 {
943 let left = <Self::Entity as RelatedSelfVia<J>>::to();
944 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
945
946 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
947 }
948
949 #[doc(hidden)]
951 fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
952 where
953 J: EntityTrait + Related<Self::Entity>,
954 C: ConnectionTrait,
955 {
956 let rel_def = <J as Related<Self::Entity>>::to();
957 let id = get_key_from_active_model(&rel_def.to_col, self)?;
958
959 J::delete_many()
960 .filter(
961 column_tuple_in_condition(
962 &rel_def.from_tbl,
963 &rel_def.from_col,
964 &[id],
965 db.get_database_backend(),
966 )
967 .expect(""),
968 )
969 .exec(db)
970 }
971
972 #[doc(hidden)]
974 fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
975 where
976 J: EntityTrait,
977 C: ConnectionTrait,
978 Self::Entity: RelatedSelfVia<J>,
979 {
980 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
981 let right = <Self::Entity as RelatedSelfVia<J>>::to();
982
983 let id = get_key_from_active_model(&left.to_col, self)?;
984
985 if left.to_col != right.to_col {
986 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
987 }
988
989 J::delete_many()
990 .filter(
991 Condition::any()
992 .add(
993 column_tuple_in_condition(
994 &left.from_tbl,
995 &left.from_col,
996 std::slice::from_ref(&id),
997 db.get_database_backend(),
998 )
999 .expect(""),
1000 )
1001 .add(
1002 column_tuple_in_condition(
1003 &right.from_tbl,
1004 &right.from_col,
1005 std::slice::from_ref(&id),
1006 db.get_database_backend(),
1007 )
1008 .expect(""),
1009 ),
1010 )
1011 .exec(db)
1012 }
1013}
1014
1015#[allow(unused_variables)]
1043pub trait ActiveModelBehavior: ActiveModelTrait {
1044 fn new() -> Self {
1057 <Self as ActiveModelTrait>::default()
1058 }
1059
1060 fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1062 where
1063 C: ConnectionTrait,
1064 {
1065 Ok(self)
1066 }
1067
1068 fn after_save<C>(
1070 model: <Self::Entity as EntityTrait>::Model,
1071 db: &C,
1072 insert: bool,
1073 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1074 where
1075 C: ConnectionTrait,
1076 {
1077 Ok(model)
1078 }
1079
1080 fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1082 where
1083 C: ConnectionTrait,
1084 {
1085 Ok(self)
1086 }
1087
1088 fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1090 where
1091 C: ConnectionTrait,
1092 {
1093 Ok(self)
1094 }
1095}
1096
1097pub trait IntoActiveModel<A>
1099where
1100 A: ActiveModelTrait,
1101{
1102 fn into_active_model(self) -> A;
1104}
1105
1106impl<A> IntoActiveModel<A> for A
1107where
1108 A: ActiveModelTrait,
1109{
1110 fn into_active_model(self) -> A {
1111 self
1112 }
1113}
1114
1115fn establish_links<EM, J, RM, C>(
1116 model: &EM,
1117 related_models: &[RM],
1118 left: RelationDef,
1119 right: RelationDef,
1120 delete_leftover: bool,
1121 db: &C,
1122) -> Result<(), DbErr>
1123where
1124 EM: ActiveModelTrait,
1125 RM: ActiveModelTrait,
1126 J: EntityTrait,
1127 J::Model: IntoActiveModel<J::ActiveModel>,
1128 J::ActiveModel: ActiveModelBehavior,
1129 C: ConnectionTrait,
1130{
1131 let mut require_leftover = true;
1132
1133 if related_models.is_empty() {
1134 require_leftover = false;
1136 }
1137
1138 let primary_key = J::primary_key_identity();
1139 if require_leftover
1140 && primary_key.fully_contains(&left.from_col)
1141 && primary_key.fully_contains(&right.from_col)
1142 {
1143 require_leftover = false;
1146 }
1147
1148 let mut leftover = Vec::new();
1149 if delete_leftover || require_leftover {
1150 for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1151 &left,
1152 model,
1153 db.get_database_backend(),
1154 )?
1155 .all(db)?
1156 {
1157 let item = item.into_active_model();
1158 let key = get_key_from_active_model(&right.from_col, &item)?;
1159 leftover.push((item, key));
1160 }
1161 }
1162 let leftover = leftover; let mut via_models = Vec::new();
1165 let mut all_keys = std::collections::HashSet::new();
1166
1167 for related_model in related_models {
1168 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1169 via.set_parent_key_for_def(model, &left)?;
1170 via.set_parent_key_for_def(related_model, &right)?;
1171 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1172 if !leftover.iter().any(|t| t.1 == via_key) {
1173 via_models.push(via);
1175 }
1176 if delete_leftover {
1177 all_keys.insert(via_key);
1178 }
1179 }
1180
1181 if delete_leftover {
1182 let mut to_delete = Vec::new();
1183 for (leftover, key) in leftover {
1184 if !all_keys.contains(&key) {
1185 to_delete.push(
1186 leftover
1187 .get_primary_key_value()
1188 .expect("item is a full model"),
1189 );
1190 }
1191 }
1192 if !to_delete.is_empty() {
1193 J::delete_many()
1194 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1195 .exec(db)?;
1196 }
1197 }
1198
1199 if !via_models.is_empty() {
1200 J::insert_many(via_models)
1202 .on_conflict_do_nothing()
1203 .exec(db)?;
1204 }
1205
1206 Ok(())
1207}
1208
1209#[cfg(test)]
1210mod tests {
1211 use crate::{DbErr, entity::*, tests_cfg::*};
1212 use pretty_assertions::assert_eq;
1213
1214 #[cfg(feature = "with-json")]
1215 use serde_json::json;
1216
1217 #[test]
1218 #[cfg(feature = "macros")]
1219 fn test_derive_into_active_model_1() {
1220 mod my_fruit {
1221 pub use super::fruit::*;
1222 use crate as sea_orm;
1223 use crate::entity::prelude::*;
1224
1225 #[derive(DeriveIntoActiveModel)]
1226 pub struct NewFruit {
1227 pub name: String,
1229 pub cake_id: i32,
1231 }
1232 }
1233
1234 assert_eq!(
1235 my_fruit::NewFruit {
1236 name: "Apple".to_owned(),
1237 cake_id: 1,
1238 }
1239 .into_active_model(),
1240 fruit::ActiveModel {
1241 id: NotSet,
1242 name: Set("Apple".to_owned()),
1243 cake_id: Set(Some(1)),
1244 }
1245 );
1246 }
1247
1248 #[test]
1249 #[cfg(feature = "macros")]
1250 fn test_derive_into_active_model_2() {
1251 use crate as sea_orm;
1252 use crate::entity::prelude::*;
1253
1254 #[derive(DeriveIntoActiveModel)]
1255 #[sea_orm(active_model = "fruit::ActiveModel")]
1256 struct RequiredFruitName {
1257 name: String,
1258 }
1259
1260 assert_eq!(
1261 RequiredFruitName {
1262 name: "Apple Pie".to_owned(),
1263 }
1264 .into_active_model(),
1265 fruit::ActiveModel {
1266 id: NotSet,
1267 name: Set("Apple Pie".to_owned()),
1268 cake_id: NotSet,
1269 }
1270 );
1271
1272 #[derive(DeriveIntoActiveModel)]
1273 #[sea_orm(active_model = "fruit::ActiveModel")]
1274 struct OptionalFruitName {
1275 name: Option<String>,
1276 }
1277
1278 assert_eq!(
1279 OptionalFruitName {
1280 name: Some("Apple Pie".to_owned()),
1281 }
1282 .into_active_model(),
1283 fruit::ActiveModel {
1284 id: NotSet,
1285 name: Set("Apple Pie".to_owned()),
1286 cake_id: NotSet,
1287 }
1288 );
1289
1290 assert_eq!(
1291 OptionalFruitName { name: None }.into_active_model(),
1292 fruit::ActiveModel {
1293 id: NotSet,
1294 name: NotSet,
1295 cake_id: NotSet,
1296 }
1297 );
1298
1299 #[derive(DeriveIntoActiveModel)]
1300 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1301 struct RequiredAndNotNullFruitCake {
1302 cake_id: i32,
1303 }
1304
1305 assert_eq!(
1306 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1307 fruit::ActiveModel {
1308 id: NotSet,
1309 name: NotSet,
1310 cake_id: Set(Some(1)),
1311 }
1312 );
1313
1314 #[derive(DeriveIntoActiveModel)]
1315 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1316 struct OptionalAndNotNullFruitCake {
1317 cake_id: Option<i32>,
1318 }
1319
1320 assert_eq!(
1321 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1322 fruit::ActiveModel {
1323 id: NotSet,
1324 name: NotSet,
1325 cake_id: Set(Some(1)),
1326 }
1327 );
1328
1329 assert_eq!(
1330 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1331 fruit::ActiveModel {
1332 id: NotSet,
1333 name: NotSet,
1334 cake_id: NotSet,
1335 }
1336 );
1337
1338 #[derive(DeriveIntoActiveModel)]
1339 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1340 struct OptionalAndNullableFruitCake {
1341 cake_id: Option<Option<i32>>,
1342 }
1343
1344 assert_eq!(
1345 OptionalAndNullableFruitCake {
1346 cake_id: Some(Some(1)),
1347 }
1348 .into_active_model(),
1349 fruit::ActiveModel {
1350 id: NotSet,
1351 name: NotSet,
1352 cake_id: Set(Some(1)),
1353 }
1354 );
1355
1356 assert_eq!(
1357 OptionalAndNullableFruitCake {
1358 cake_id: Some(None),
1359 }
1360 .into_active_model(),
1361 fruit::ActiveModel {
1362 id: NotSet,
1363 name: NotSet,
1364 cake_id: Set(None),
1365 }
1366 );
1367
1368 assert_eq!(
1369 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1370 fruit::ActiveModel {
1371 id: NotSet,
1372 name: NotSet,
1373 cake_id: NotSet,
1374 }
1375 );
1376 }
1377
1378 #[test]
1379 #[cfg(feature = "macros")]
1380 fn test_derive_try_into_model_1() {
1381 mod my_fruit {
1382 use crate as sea_orm;
1383 use crate::entity::prelude::*;
1384
1385 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1386 #[sea_orm(table_name = "fruit")]
1387 pub struct Model {
1388 #[sea_orm(primary_key)]
1389 pub id: i32,
1390 pub name: String,
1391 pub cake_id: Option<i32>,
1392 }
1393
1394 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1395 pub enum Relation {}
1396
1397 impl ActiveModelBehavior for ActiveModel {}
1398 }
1399 assert_eq!(
1400 my_fruit::ActiveModel {
1401 id: Set(1),
1402 name: Set("Pineapple".to_owned()),
1403 cake_id: Set(None),
1404 }
1405 .try_into_model()
1406 .unwrap(),
1407 my_fruit::Model {
1408 id: 1,
1409 name: "Pineapple".to_owned(),
1410 cake_id: None,
1411 }
1412 );
1413
1414 assert_eq!(
1415 my_fruit::ActiveModel {
1416 id: Set(2),
1417 name: Set("Apple".to_owned()),
1418 cake_id: Set(Some(1)),
1419 }
1420 .try_into_model()
1421 .unwrap(),
1422 my_fruit::Model {
1423 id: 2,
1424 name: "Apple".to_owned(),
1425 cake_id: Some(1),
1426 }
1427 );
1428
1429 assert_eq!(
1430 my_fruit::ActiveModel {
1431 id: Set(1),
1432 name: NotSet,
1433 cake_id: Set(None),
1434 }
1435 .try_into_model(),
1436 Err(DbErr::AttrNotSet(String::from("name")))
1437 );
1438
1439 assert_eq!(
1440 my_fruit::ActiveModel {
1441 id: Set(1),
1442 name: Set("Pineapple".to_owned()),
1443 cake_id: NotSet,
1444 }
1445 .try_into_model(),
1446 Err(DbErr::AttrNotSet(String::from("cake_id")))
1447 );
1448 }
1449
1450 #[test]
1451 #[cfg(feature = "macros")]
1452 fn test_derive_try_into_model_2() {
1453 mod my_fruit {
1454 use crate as sea_orm;
1455 use crate::entity::prelude::*;
1456
1457 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1458 #[sea_orm(table_name = "fruit")]
1459 pub struct Model {
1460 #[sea_orm(primary_key)]
1461 pub id: i32,
1462 pub name: String,
1463 #[sea_orm(ignore)]
1464 pub cake_id: Option<i32>,
1465 }
1466
1467 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1468 pub enum Relation {}
1469
1470 impl ActiveModelBehavior for ActiveModel {}
1471 }
1472 assert_eq!(
1473 my_fruit::ActiveModel {
1474 id: Set(1),
1475 name: Set("Pineapple".to_owned()),
1476 }
1477 .try_into_model()
1478 .unwrap(),
1479 my_fruit::Model {
1480 id: 1,
1481 name: "Pineapple".to_owned(),
1482 cake_id: None,
1483 }
1484 );
1485 }
1486
1487 #[test]
1488 #[cfg(feature = "macros")]
1489 fn test_derive_try_into_model_3() {
1490 mod my_fruit {
1491 use crate as sea_orm;
1492 use crate::entity::prelude::*;
1493
1494 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1495 #[sea_orm(table_name = "fruit")]
1496 pub struct Model {
1497 #[sea_orm(primary_key)]
1498 pub id: i32,
1499 #[sea_orm(ignore)]
1500 pub name: String,
1501 pub cake_id: Option<i32>,
1502 }
1503
1504 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1505 pub enum Relation {}
1506
1507 impl ActiveModelBehavior for ActiveModel {}
1508 }
1509 assert_eq!(
1510 my_fruit::ActiveModel {
1511 id: Set(1),
1512 cake_id: Set(Some(1)),
1513 }
1514 .try_into_model()
1515 .unwrap(),
1516 my_fruit::Model {
1517 id: 1,
1518 name: "".to_owned(),
1519 cake_id: Some(1),
1520 }
1521 );
1522 }
1523
1524 #[test]
1525 #[cfg(feature = "with-json")]
1526 fn test_active_model_set_from_json_1() {
1527 assert_eq!(
1528 cake::ActiveModel::from_json(json!({
1529 "id": 1,
1530 "name": "Apple Pie",
1531 }))
1532 .unwrap(),
1533 cake::ActiveModel {
1534 id: Set(1),
1535 name: Set("Apple Pie".to_owned()),
1536 }
1537 );
1538
1539 assert_eq!(
1540 cake::ActiveModel::from_json(json!({
1541 "id": 1,
1542 }))
1543 .unwrap(),
1544 cake::ActiveModel {
1545 id: Set(1),
1546 name: NotSet,
1547 }
1548 );
1549
1550 assert_eq!(
1551 cake::ActiveModel::from_json(json!({
1552 "name": "Apple Pie",
1553 }))
1554 .unwrap(),
1555 cake::ActiveModel {
1556 id: NotSet,
1557 name: Set("Apple Pie".to_owned()),
1558 }
1559 );
1560
1561 let mut cake: cake::ActiveModel = Default::default();
1562 cake.set_from_json(json!({
1563 "name": "Apple Pie",
1564 }))
1565 .unwrap();
1566 assert_eq!(
1567 cake,
1568 cake::ActiveModel {
1569 id: NotSet,
1570 name: Set("Apple Pie".to_owned()),
1571 }
1572 );
1573 }
1574
1575 #[test]
1576 #[cfg(feature = "with-json")]
1577 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1578 let mut fruit: fruit::ActiveModel = Default::default();
1579
1580 fruit.set_from_json(json!({
1581 "name": "Apple",
1582 }))?;
1583 assert_eq!(
1584 fruit,
1585 fruit::ActiveModel {
1586 id: ActiveValue::NotSet,
1587 name: ActiveValue::Set("Apple".to_owned()),
1588 cake_id: ActiveValue::NotSet,
1589 }
1590 );
1591
1592 assert_eq!(
1593 fruit::ActiveModel::from_json(json!({
1594 "name": "Apple",
1595 }))?,
1596 fruit::ActiveModel {
1597 id: ActiveValue::NotSet,
1598 name: ActiveValue::Set("Apple".to_owned()),
1599 cake_id: ActiveValue::NotSet,
1600 }
1601 );
1602
1603 fruit.set_from_json(json!({
1604 "name": "Apple",
1605 "cake_id": null,
1606 }))?;
1607 assert_eq!(
1608 fruit,
1609 fruit::ActiveModel {
1610 id: ActiveValue::NotSet,
1611 name: ActiveValue::Set("Apple".to_owned()),
1612 cake_id: ActiveValue::Set(None),
1613 }
1614 );
1615
1616 fruit.set_from_json(json!({
1617 "id": null,
1618 "name": "Apple",
1619 "cake_id": 1,
1620 }))?;
1621 assert_eq!(
1622 fruit,
1623 fruit::ActiveModel {
1624 id: ActiveValue::NotSet,
1625 name: ActiveValue::Set("Apple".to_owned()),
1626 cake_id: ActiveValue::Set(Some(1)),
1627 }
1628 );
1629
1630 fruit.set_from_json(json!({
1631 "id": 2,
1632 "name": "Apple",
1633 "cake_id": 1,
1634 }))?;
1635 assert_eq!(
1636 fruit,
1637 fruit::ActiveModel {
1638 id: ActiveValue::NotSet,
1639 name: ActiveValue::Set("Apple".to_owned()),
1640 cake_id: ActiveValue::Set(Some(1)),
1641 }
1642 );
1643
1644 let mut fruit = fruit::ActiveModel {
1645 id: ActiveValue::Set(1),
1646 name: ActiveValue::NotSet,
1647 cake_id: ActiveValue::NotSet,
1648 };
1649 fruit.set_from_json(json!({
1650 "id": 8,
1651 "name": "Apple",
1652 "cake_id": 1,
1653 }))?;
1654 assert_eq!(
1655 fruit,
1656 fruit::ActiveModel {
1657 id: ActiveValue::Set(1),
1658 name: ActiveValue::Set("Apple".to_owned()),
1659 cake_id: ActiveValue::Set(Some(1)),
1660 }
1661 );
1662
1663 Ok(())
1664 }
1665
1666 #[test]
1667 #[cfg(feature = "with-json")]
1668 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1669 use crate::*;
1670
1671 let db = MockDatabase::new(DbBackend::Postgres)
1672 .append_exec_results([
1673 MockExecResult {
1674 last_insert_id: 1,
1675 rows_affected: 1,
1676 },
1677 MockExecResult {
1678 last_insert_id: 1,
1679 rows_affected: 1,
1680 },
1681 ])
1682 .append_query_results([
1683 [fruit::Model {
1684 id: 1,
1685 name: "Apple".to_owned(),
1686 cake_id: None,
1687 }],
1688 [fruit::Model {
1689 id: 2,
1690 name: "Orange".to_owned(),
1691 cake_id: Some(1),
1692 }],
1693 ])
1694 .into_connection();
1695
1696 let mut fruit: fruit::ActiveModel = Default::default();
1697 fruit.set_from_json(json!({
1698 "name": "Apple",
1699 }))?;
1700 fruit.save(&db)?;
1701
1702 let mut fruit = fruit::ActiveModel {
1703 id: Set(2),
1704 ..Default::default()
1705 };
1706 fruit.set_from_json(json!({
1707 "id": 9,
1708 "name": "Orange",
1709 "cake_id": 1,
1710 }))?;
1711 fruit.save(&db)?;
1712
1713 assert_eq!(
1714 db.into_transaction_log(),
1715 [
1716 Transaction::from_sql_and_values(
1717 DbBackend::Postgres,
1718 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1719 ["Apple".into()],
1720 ),
1721 Transaction::from_sql_and_values(
1722 DbBackend::Postgres,
1723 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1724 ["Orange".into(), 1i32.into(), 2i32.into()],
1725 ),
1726 ]
1727 );
1728
1729 Ok(())
1730 }
1731
1732 #[test]
1733 fn test_active_model_is_changed() {
1734 let mut fruit: fruit::ActiveModel = Default::default();
1735 assert!(!fruit.is_changed());
1736
1737 fruit.set(fruit::Column::Name, "apple".into());
1738 assert!(fruit.is_changed());
1739
1740 let mut fruit = fruit::Model {
1741 id: 1,
1742 name: "".into(),
1743 cake_id: None,
1744 };
1745 fruit.set("name".parse().unwrap(), "orange".into());
1746 assert_eq!(fruit.name, "orange");
1747 }
1748
1749 #[test]
1750 fn test_reset_1() {
1751 assert_eq!(
1752 fruit::Model {
1753 id: 1,
1754 name: "Apple".into(),
1755 cake_id: None,
1756 }
1757 .into_active_model(),
1758 fruit::ActiveModel {
1759 id: Unchanged(1),
1760 name: Unchanged("Apple".into()),
1761 cake_id: Unchanged(None)
1762 },
1763 );
1764
1765 assert_eq!(
1766 fruit::Model {
1767 id: 1,
1768 name: "Apple".into(),
1769 cake_id: None,
1770 }
1771 .into_active_model()
1772 .reset_all(),
1773 fruit::ActiveModel {
1774 id: Set(1),
1775 name: Set("Apple".into()),
1776 cake_id: Set(None)
1777 },
1778 );
1779
1780 assert_eq!(
1781 fruit::Model {
1782 id: 1,
1783 name: "Apple".into(),
1784 cake_id: Some(2),
1785 }
1786 .into_active_model(),
1787 fruit::ActiveModel {
1788 id: Unchanged(1),
1789 name: Unchanged("Apple".into()),
1790 cake_id: Unchanged(Some(2)),
1791 },
1792 );
1793
1794 assert_eq!(
1795 fruit::Model {
1796 id: 1,
1797 name: "Apple".into(),
1798 cake_id: Some(2),
1799 }
1800 .into_active_model()
1801 .reset_all(),
1802 fruit::ActiveModel {
1803 id: Set(1),
1804 name: Set("Apple".into()),
1805 cake_id: Set(Some(2)),
1806 },
1807 );
1808 }
1809
1810 #[test]
1811 fn test_reset_2() -> Result<(), DbErr> {
1812 use crate::*;
1813
1814 let db = MockDatabase::new(DbBackend::Postgres)
1815 .append_exec_results(vec![
1816 MockExecResult {
1817 last_insert_id: 1,
1818 rows_affected: 1,
1819 },
1820 MockExecResult {
1821 last_insert_id: 1,
1822 rows_affected: 1,
1823 },
1824 ])
1825 .append_query_results(vec![
1826 vec![fruit::Model {
1827 id: 1,
1828 name: "Apple".to_owned(),
1829 cake_id: None,
1830 }],
1831 vec![fruit::Model {
1832 id: 1,
1833 name: "Apple".to_owned(),
1834 cake_id: None,
1835 }],
1836 ])
1837 .into_connection();
1838
1839 fruit::Model {
1840 id: 1,
1841 name: "Apple".into(),
1842 cake_id: None,
1843 }
1844 .into_active_model()
1845 .update(&db)?;
1846
1847 fruit::Model {
1848 id: 1,
1849 name: "Apple".into(),
1850 cake_id: None,
1851 }
1852 .into_active_model()
1853 .reset_all()
1854 .update(&db)?;
1855
1856 assert_eq!(
1857 db.into_transaction_log(),
1858 vec![
1859 Transaction::from_sql_and_values(
1860 DbBackend::Postgres,
1861 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1862 vec![1i32.into(), 1u64.into()],
1863 ),
1864 Transaction::from_sql_and_values(
1865 DbBackend::Postgres,
1866 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1867 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1868 ),
1869 ]
1870 );
1871
1872 Ok(())
1873 }
1874
1875 #[test]
1876 fn test_active_model_default_values() {
1877 assert_eq!(
1878 fruit::ActiveModel::default_values(),
1879 fruit::ActiveModel {
1880 id: Set(0),
1881 name: Set("".into()),
1882 cake_id: Set(None),
1883 },
1884 );
1885
1886 assert_eq!(
1887 lunch_set::ActiveModel::default_values(),
1888 lunch_set::ActiveModel {
1889 id: Set(0),
1890 name: Set("".into()),
1891 tea: NotSet,
1892 },
1893 );
1894 }
1895
1896 #[test]
1897 fn test_active_model_set_parent_key() {
1898 let mut fruit = fruit::Model {
1899 id: 2,
1900 name: "F".into(),
1901 cake_id: None,
1902 }
1903 .into_active_model();
1904
1905 let cake = cake::Model {
1906 id: 4,
1907 name: "C".into(),
1908 }
1909 .into_active_model();
1910
1911 fruit.set_parent_key(&cake).unwrap();
1912
1913 assert_eq!(
1914 fruit,
1915 fruit::ActiveModel {
1916 id: Unchanged(2),
1917 name: Unchanged("F".into()),
1918 cake_id: Set(Some(4)),
1919 }
1920 );
1921
1922 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1923
1924 assert_eq!(
1925 fruit,
1926 fruit::ActiveModel {
1927 id: Unchanged(2),
1928 name: Unchanged("F".into()),
1929 cake_id: Set(None),
1930 }
1931 );
1932
1933 let mut cake_filling = cake_filling::ActiveModel::new();
1934
1935 cake_filling.set_parent_key(&cake).unwrap();
1936
1937 assert_eq!(
1938 cake_filling,
1939 cake_filling::ActiveModel {
1940 cake_id: Set(4),
1941 filling_id: NotSet,
1942 }
1943 );
1944 }
1945}