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>
1182where
1183 A: ActiveModelTrait,
1184{
1185 fn into_active_model(self) -> A;
1187}
1188
1189impl<A> IntoActiveModel<A> for A
1190where
1191 A: ActiveModelTrait,
1192{
1193 fn into_active_model(self) -> A {
1194 self
1195 }
1196}
1197
1198fn establish_links<EM, J, RM, C>(
1199 model: &EM,
1200 related_models: &[RM],
1201 left: RelationDef,
1202 right: RelationDef,
1203 delete_leftover: bool,
1204 db: &C,
1205) -> Result<(), DbErr>
1206where
1207 EM: ActiveModelTrait,
1208 RM: ActiveModelTrait,
1209 J: EntityTrait,
1210 J::Model: IntoActiveModel<J::ActiveModel>,
1211 J::ActiveModel: ActiveModelBehavior,
1212 C: ConnectionTrait,
1213{
1214 let mut require_leftover = true;
1215
1216 if related_models.is_empty() {
1217 require_leftover = false;
1219 }
1220
1221 let primary_key = J::primary_key_identity();
1222 if require_leftover
1223 && primary_key.fully_contains(&left.from_col)
1224 && primary_key.fully_contains(&right.from_col)
1225 {
1226 require_leftover = false;
1229 }
1230
1231 let mut leftover = Vec::new();
1232 if delete_leftover || require_leftover {
1233 for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1234 &left,
1235 model,
1236 db.get_database_backend(),
1237 )?
1238 .all(db)?
1239 {
1240 let item = item.into_active_model();
1241 let key = get_key_from_active_model(&right.from_col, &item)?;
1242 leftover.push((item, key));
1243 }
1244 }
1245 let leftover = leftover; let mut via_models = Vec::new();
1248 let mut all_keys = std::collections::HashSet::new();
1249
1250 for related_model in related_models {
1251 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1252 via.set_parent_key_for_def(model, &left)?;
1253 via.set_parent_key_for_def(related_model, &right)?;
1254 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1255 if !leftover.iter().any(|t| t.1 == via_key) {
1256 via_models.push(via);
1258 }
1259 if delete_leftover {
1260 all_keys.insert(via_key);
1261 }
1262 }
1263
1264 if delete_leftover {
1265 let mut to_delete = Vec::new();
1266 for (leftover, key) in leftover {
1267 if !all_keys.contains(&key) {
1268 to_delete.push(
1269 leftover
1270 .get_primary_key_value()
1271 .expect("item is a full model"),
1272 );
1273 }
1274 }
1275 if !to_delete.is_empty() {
1276 J::delete_many()
1277 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1278 .exec(db)?;
1279 }
1280 }
1281
1282 if !via_models.is_empty() {
1283 J::insert_many(via_models)
1285 .on_conflict_do_nothing()
1286 .exec(db)?;
1287 }
1288
1289 Ok(())
1290}
1291
1292#[cfg(test)]
1293mod tests {
1294 use crate::{DbErr, entity::*, tests_cfg::*};
1295 use pretty_assertions::assert_eq;
1296
1297 #[cfg(feature = "with-json")]
1298 use serde_json::json;
1299
1300 #[test]
1301 #[cfg(feature = "macros")]
1302 fn test_derive_into_active_model_1() {
1303 mod my_fruit {
1304 pub use super::fruit::*;
1305 use crate as sea_orm;
1306 use crate::entity::prelude::*;
1307
1308 #[derive(DeriveIntoActiveModel)]
1309 pub struct NewFruit {
1310 pub name: String,
1312 pub cake_id: i32,
1314 }
1315 }
1316
1317 assert_eq!(
1318 my_fruit::NewFruit {
1319 name: "Apple".to_owned(),
1320 cake_id: 1,
1321 }
1322 .into_active_model(),
1323 fruit::ActiveModel {
1324 id: NotSet,
1325 name: Set("Apple".to_owned()),
1326 cake_id: Set(Some(1)),
1327 }
1328 );
1329 }
1330
1331 #[test]
1332 #[cfg(feature = "macros")]
1333 fn test_derive_into_active_model_2() {
1334 use crate as sea_orm;
1335 use crate::entity::prelude::*;
1336
1337 #[derive(DeriveIntoActiveModel)]
1338 #[sea_orm(active_model = "fruit::ActiveModel")]
1339 struct RequiredFruitName {
1340 name: String,
1341 }
1342
1343 assert_eq!(
1344 RequiredFruitName {
1345 name: "Apple Pie".to_owned(),
1346 }
1347 .into_active_model(),
1348 fruit::ActiveModel {
1349 id: NotSet,
1350 name: Set("Apple Pie".to_owned()),
1351 cake_id: NotSet,
1352 }
1353 );
1354
1355 #[derive(DeriveIntoActiveModel)]
1356 #[sea_orm(active_model = "fruit::ActiveModel")]
1357 struct OptionalFruitName {
1358 name: Option<String>,
1359 }
1360
1361 assert_eq!(
1362 OptionalFruitName {
1363 name: Some("Apple Pie".to_owned()),
1364 }
1365 .into_active_model(),
1366 fruit::ActiveModel {
1367 id: NotSet,
1368 name: Set("Apple Pie".to_owned()),
1369 cake_id: NotSet,
1370 }
1371 );
1372
1373 assert_eq!(
1374 OptionalFruitName { name: None }.into_active_model(),
1375 fruit::ActiveModel {
1376 id: NotSet,
1377 name: NotSet,
1378 cake_id: NotSet,
1379 }
1380 );
1381
1382 #[derive(DeriveIntoActiveModel)]
1383 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1384 struct RequiredAndNotNullFruitCake {
1385 cake_id: i32,
1386 }
1387
1388 assert_eq!(
1389 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1390 fruit::ActiveModel {
1391 id: NotSet,
1392 name: NotSet,
1393 cake_id: Set(Some(1)),
1394 }
1395 );
1396
1397 #[derive(DeriveIntoActiveModel)]
1398 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1399 struct OptionalAndNotNullFruitCake {
1400 cake_id: Option<i32>,
1401 }
1402
1403 assert_eq!(
1404 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1405 fruit::ActiveModel {
1406 id: NotSet,
1407 name: NotSet,
1408 cake_id: Set(Some(1)),
1409 }
1410 );
1411
1412 assert_eq!(
1413 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1414 fruit::ActiveModel {
1415 id: NotSet,
1416 name: NotSet,
1417 cake_id: NotSet,
1418 }
1419 );
1420
1421 #[derive(DeriveIntoActiveModel)]
1422 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1423 struct OptionalAndNullableFruitCake {
1424 cake_id: Option<Option<i32>>,
1425 }
1426
1427 assert_eq!(
1428 OptionalAndNullableFruitCake {
1429 cake_id: Some(Some(1)),
1430 }
1431 .into_active_model(),
1432 fruit::ActiveModel {
1433 id: NotSet,
1434 name: NotSet,
1435 cake_id: Set(Some(1)),
1436 }
1437 );
1438
1439 assert_eq!(
1440 OptionalAndNullableFruitCake {
1441 cake_id: Some(None),
1442 }
1443 .into_active_model(),
1444 fruit::ActiveModel {
1445 id: NotSet,
1446 name: NotSet,
1447 cake_id: Set(None),
1448 }
1449 );
1450
1451 assert_eq!(
1452 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1453 fruit::ActiveModel {
1454 id: NotSet,
1455 name: NotSet,
1456 cake_id: NotSet,
1457 }
1458 );
1459 }
1460
1461 #[test]
1462 #[cfg(feature = "macros")]
1463 fn test_derive_into_active_model_fill_single() {
1464 use crate as sea_orm;
1465 use crate::entity::prelude::*;
1466
1467 #[derive(DeriveIntoActiveModel)]
1468 #[sea_orm(active_model = "fruit::ActiveModel", fill(cake_id = "None"))]
1469 struct NewFruit {
1470 name: String,
1471 }
1472
1473 assert_eq!(
1474 NewFruit {
1475 name: "Apple".to_owned(),
1476 }
1477 .into_active_model(),
1478 fruit::ActiveModel {
1479 id: NotSet,
1480 name: Set("Apple".to_owned()),
1481 cake_id: Set(None),
1482 }
1483 );
1484 }
1485
1486 #[test]
1487 #[cfg(feature = "macros")]
1488 fn test_derive_into_active_model_set_multiple() {
1489 use crate as sea_orm;
1490 use crate::entity::prelude::*;
1491
1492 #[derive(DeriveIntoActiveModel)]
1493 #[sea_orm(
1494 active_model = "fruit::ActiveModel",
1495 set(name = "String::from(\"cherry\")", cake_id = "None")
1496 )]
1497 struct IdOnlyFruit {
1498 id: i32,
1499 }
1500 assert_eq!(
1501 IdOnlyFruit { id: 1 }.into_active_model(),
1502 fruit::ActiveModel {
1503 id: Set(1),
1504 name: Set("cherry".to_owned()),
1505 cake_id: Set(None),
1506 }
1507 );
1508
1509 #[derive(DeriveIntoActiveModel)]
1510 #[sea_orm(
1511 active_model = "fruit::ActiveModel",
1512 set(name = "String::from(\"cherry\")"),
1513 set(cake_id = "None")
1514 )]
1515 struct IdOnlyFruit2 {
1516 id: i32,
1517 }
1518 assert_eq!(
1519 IdOnlyFruit2 { id: 1 }.into_active_model(),
1520 fruit::ActiveModel {
1521 id: Set(1),
1522 name: Set("cherry".to_owned()),
1523 cake_id: Set(None),
1524 }
1525 );
1526 }
1527
1528 #[test]
1529 #[cfg(feature = "macros")]
1530 fn test_derive_into_active_model_set_separate_attrs() {
1531 use crate as sea_orm;
1532 use crate::entity::prelude::*;
1533
1534 #[derive(DeriveIntoActiveModel)]
1535 #[sea_orm(
1536 active_model = "fruit::ActiveModel",
1537 set(name = "String::from(\"cherry\")")
1538 )]
1539 #[sea_orm(set(cake_id = "None"))]
1540 struct IdOnlyFruit {
1541 id: i32,
1542 }
1543
1544 assert_eq!(
1545 IdOnlyFruit { id: 1 }.into_active_model(),
1546 fruit::ActiveModel {
1547 id: Set(1),
1548 name: Set("cherry".to_owned()),
1549 cake_id: Set(None),
1550 }
1551 );
1552 }
1553
1554 #[test]
1555 #[cfg(feature = "macros")]
1556 fn test_derive_into_active_model_ignore() {
1557 use crate as sea_orm;
1558 use crate::entity::prelude::*;
1559
1560 #[derive(DeriveIntoActiveModel)]
1561 #[sea_orm(active_model = "fruit::ActiveModel")]
1562 struct NewFruit {
1563 name: String,
1564 cake_id: i32,
1565 #[sea_orm(ignore)]
1566 _extra: String,
1567 }
1568
1569 assert_eq!(
1570 NewFruit {
1571 name: "Apple".to_owned(),
1572 cake_id: 1,
1573 _extra: "ignored".to_owned(),
1574 }
1575 .into_active_model(),
1576 fruit::ActiveModel {
1577 id: NotSet,
1578 name: Set("Apple".to_owned()),
1579 cake_id: Set(Some(1)),
1580 }
1581 );
1582 }
1583
1584 #[test]
1585 #[cfg(feature = "macros")]
1586 fn test_derive_into_active_model_skip() {
1587 use crate as sea_orm;
1588 use crate::entity::prelude::*;
1589
1590 #[derive(DeriveIntoActiveModel)]
1591 #[sea_orm(active_model = "fruit::ActiveModel")]
1592 struct NewFruit {
1593 name: String,
1594 #[sea_orm(skip)]
1595 _extra: String,
1596 }
1597
1598 assert_eq!(
1599 NewFruit {
1600 name: "Apple".to_owned(),
1601 _extra: "skipped".to_owned(),
1602 }
1603 .into_active_model(),
1604 fruit::ActiveModel {
1605 id: NotSet,
1606 name: Set("Apple".to_owned()),
1607 cake_id: NotSet,
1608 }
1609 );
1610 }
1611
1612 #[test]
1613 #[cfg(feature = "macros")]
1614 fn test_derive_into_active_model_set_and_ignore() {
1615 use crate as sea_orm;
1616 use crate::entity::prelude::*;
1617
1618 #[derive(DeriveIntoActiveModel)]
1619 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
1620 struct NewFruit {
1621 name: String,
1622 #[sea_orm(ignore)]
1623 _extra: String,
1624 }
1625
1626 assert_eq!(
1627 NewFruit {
1628 name: "Apple".to_owned(),
1629 _extra: "ignored".to_owned(),
1630 }
1631 .into_active_model(),
1632 fruit::ActiveModel {
1633 id: NotSet,
1634 name: Set("Apple".to_owned()),
1635 cake_id: Set(Some(42)),
1636 }
1637 );
1638 }
1639
1640 #[test]
1641 #[cfg(feature = "macros")]
1642 fn test_derive_into_active_model_foreign_ignore() {
1643 use serde::{Deserialize, Serialize};
1644
1645 use crate as sea_orm;
1646 use crate::entity::prelude::*;
1647
1648 #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
1649 #[sea_orm(active_model = "fruit::ActiveModel")]
1650 struct NewFruit {
1651 #[sea_orm(ignore)]
1652 id: i32,
1653 name: String,
1654 #[serde(skip)]
1655 cake_id: Option<i32>,
1656 }
1657
1658 assert_eq!(
1659 NewFruit {
1660 id: 1.to_owned(),
1661 name: "Apple".to_owned(),
1662 cake_id: Some(42)
1663 }
1664 .into_active_model(),
1665 fruit::ActiveModel {
1666 id: NotSet,
1667 name: Set("Apple".to_owned()),
1668 cake_id: Set(Some(42)),
1669 }
1670 );
1671 }
1672
1673 #[test]
1674 #[cfg(feature = "macros")]
1675 fn test_derive_into_active_model_exhaustive() {
1676 use crate as sea_orm;
1677 use crate::entity::prelude::*;
1678
1679 #[derive(DeriveIntoActiveModel)]
1680 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1681 struct FullFruit {
1682 id: i32,
1683 name: String,
1684 }
1685
1686 assert_eq!(
1687 FullFruit {
1688 id: 1,
1689 name: "Apple".to_owned(),
1690 }
1691 .into_active_model(),
1692 fruit::ActiveModel {
1693 id: Set(1),
1694 name: Set("Apple".to_owned()),
1695 cake_id: Set(None),
1696 }
1697 );
1698 }
1699
1700 #[test]
1701 #[cfg(feature = "macros")]
1702 fn test_derive_into_active_model_multiple_sets() {
1703 use crate as sea_orm;
1704 use crate::entity::prelude::*;
1705
1706 const DEFULT_CAKE_ID: i32 = 1;
1707 #[derive(DeriveIntoActiveModel)]
1708 #[sea_orm(
1709 active_model = "fruit::ActiveModel",
1710 exhaustive,
1711 set(cake_id = "Some(DEFULT_CAKE_ID)")
1712 )]
1713 struct FullFruit {
1714 id: i32,
1715 name: String,
1716 }
1717
1718 assert_eq!(
1719 FullFruit {
1720 id: 1,
1721 name: "Apple".to_owned(),
1722 }
1723 .into_active_model(),
1724 fruit::ActiveModel {
1725 id: Set(1),
1726 name: Set("Apple".to_owned()),
1727 cake_id: Set(Some(1)),
1728 }
1729 );
1730 }
1731
1732 #[test]
1733 #[cfg(feature = "macros")]
1734 fn test_derive_into_active_model_field_empty_default() {
1735 use crate as sea_orm;
1736 use crate::entity::prelude::*;
1737
1738 #[derive(DeriveIntoActiveModel)]
1739 #[sea_orm(active_model = "fruit::ActiveModel")]
1740 struct NewFruit {
1741 #[sea_orm(default)]
1742 name: Option<String>,
1743 }
1744
1745 assert_eq!(
1747 NewFruit {
1748 name: Some("Apple".to_owned()),
1749 }
1750 .into_active_model(),
1751 fruit::ActiveModel {
1752 id: NotSet,
1753 name: Set("Apple".to_owned()),
1754 cake_id: NotSet,
1755 }
1756 );
1757
1758 assert_eq!(
1760 NewFruit { name: None }.into_active_model(),
1761 fruit::ActiveModel {
1762 id: NotSet,
1763 name: Set("".to_owned()),
1764 cake_id: NotSet,
1765 }
1766 );
1767 }
1768
1769 #[test]
1770 #[cfg(feature = "macros")]
1771 fn test_derive_into_active_model_field_custom_option() {
1772 use crate as sea_orm;
1773 use crate::entity::prelude::*;
1774 mod foreign_crate {
1775 #[derive(Debug, Clone, PartialEq, Eq)]
1776 pub enum CustomOption<T> {
1777 None,
1778 Some(T),
1779 }
1780
1781 impl From<CustomOption<String>> for Option<String> {
1782 fn from(option: CustomOption<String>) -> Self {
1783 match option {
1784 CustomOption::None => Option::None,
1785 CustomOption::Some(value) => value.into(),
1786 }
1787 }
1788 }
1789 }
1790 use foreign_crate::CustomOption;
1791
1792 #[derive(DeriveIntoActiveModel)]
1793 #[sea_orm(active_model = "fruit::ActiveModel")]
1794 struct NewFruit {
1795 #[sea_orm(default)]
1796 name: CustomOption<String>,
1797 }
1798
1799 assert_eq!(
1801 NewFruit {
1802 name: CustomOption::Some("Apple".to_owned()),
1803 }
1804 .into_active_model(),
1805 fruit::ActiveModel {
1806 id: NotSet,
1807 name: Set("Apple".to_owned()),
1808 cake_id: NotSet,
1809 }
1810 );
1811
1812 assert_eq!(
1814 NewFruit {
1815 name: CustomOption::None
1816 }
1817 .into_active_model(),
1818 fruit::ActiveModel {
1819 id: NotSet,
1820 name: Set("".to_owned()),
1821 cake_id: NotSet,
1822 }
1823 );
1824 }
1825
1826 #[test]
1827 #[cfg(feature = "macros")]
1828 fn test_derive_into_active_model_field_default_some() {
1829 use crate as sea_orm;
1830 use crate::entity::prelude::*;
1831
1832 #[derive(DeriveIntoActiveModel)]
1833 #[sea_orm(active_model = "fruit::ActiveModel")]
1834 struct NewFruit {
1835 #[sea_orm(default = "String::from(\"Unnamed\")")]
1836 name: Option<String>,
1837 }
1838
1839 assert_eq!(
1841 NewFruit {
1842 name: Some("Apple".to_owned()),
1843 }
1844 .into_active_model(),
1845 fruit::ActiveModel {
1846 id: NotSet,
1847 name: Set("Apple".to_owned()),
1848 cake_id: NotSet,
1849 }
1850 );
1851
1852 assert_eq!(
1854 NewFruit { name: None }.into_active_model(),
1855 fruit::ActiveModel {
1856 id: NotSet,
1857 name: Set("Unnamed".to_owned()),
1858 cake_id: NotSet,
1859 }
1860 );
1861 }
1862
1863 #[test]
1864 #[cfg(feature = "macros")]
1865 fn test_derive_into_active_model_field_default_with_set() {
1866 use crate as sea_orm;
1867 use crate::entity::prelude::*;
1868
1869 #[derive(DeriveIntoActiveModel)]
1870 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
1871 struct NewFruit {
1872 #[sea_orm(default = "String::from(\"Unnamed\")")]
1873 name: Option<String>,
1874 #[sea_orm(ignore)]
1875 _extra: String,
1876 }
1877
1878 assert_eq!(
1879 NewFruit {
1880 name: Some("Apple".to_owned()),
1881 _extra: "ignored".to_owned(),
1882 }
1883 .into_active_model(),
1884 fruit::ActiveModel {
1885 id: NotSet,
1886 name: Set("Apple".to_owned()),
1887 cake_id: Set(Some(99)),
1888 }
1889 );
1890
1891 assert_eq!(
1892 NewFruit {
1893 name: None,
1894 _extra: "ignored".to_owned(),
1895 }
1896 .into_active_model(),
1897 fruit::ActiveModel {
1898 id: NotSet,
1899 name: Set("Unnamed".to_owned()),
1900 cake_id: Set(Some(99)),
1901 }
1902 );
1903 }
1904
1905 #[test]
1906 #[cfg(feature = "macros")]
1907 fn test_derive_into_active_model_field_default_exhaustive() {
1908 use crate as sea_orm;
1909 use crate::entity::prelude::*;
1910
1911 #[derive(DeriveIntoActiveModel)]
1912 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1913 struct NewFruit {
1914 id: i32,
1915 #[sea_orm(default = "String::from(\"Unnamed\")")]
1916 name: Option<String>,
1917 }
1918
1919 assert_eq!(
1920 NewFruit {
1921 id: 1,
1922 name: Some("Apple".to_owned()),
1923 }
1924 .into_active_model(),
1925 fruit::ActiveModel {
1926 id: Set(1),
1927 name: Set("Apple".to_owned()),
1928 cake_id: Set(None),
1929 }
1930 );
1931
1932 assert_eq!(
1933 NewFruit { id: 2, name: None }.into_active_model(),
1934 fruit::ActiveModel {
1935 id: Set(2),
1936 name: Set("Unnamed".to_owned()),
1937 cake_id: Set(None),
1938 }
1939 );
1940 }
1941
1942 #[test]
1943 #[cfg(feature = "macros")]
1944 fn test_derive_try_into_model_1() {
1945 mod my_fruit {
1946 use crate as sea_orm;
1947 use crate::entity::prelude::*;
1948
1949 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1950 #[sea_orm(table_name = "fruit")]
1951 pub struct Model {
1952 #[sea_orm(primary_key)]
1953 pub id: i32,
1954 pub name: String,
1955 pub cake_id: Option<i32>,
1956 }
1957
1958 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1959 pub enum Relation {}
1960
1961 impl ActiveModelBehavior for ActiveModel {}
1962 }
1963 assert_eq!(
1964 my_fruit::ActiveModel {
1965 id: Set(1),
1966 name: Set("Pineapple".to_owned()),
1967 cake_id: Set(None),
1968 }
1969 .try_into_model()
1970 .unwrap(),
1971 my_fruit::Model {
1972 id: 1,
1973 name: "Pineapple".to_owned(),
1974 cake_id: None,
1975 }
1976 );
1977
1978 assert_eq!(
1979 my_fruit::ActiveModel {
1980 id: Set(2),
1981 name: Set("Apple".to_owned()),
1982 cake_id: Set(Some(1)),
1983 }
1984 .try_into_model()
1985 .unwrap(),
1986 my_fruit::Model {
1987 id: 2,
1988 name: "Apple".to_owned(),
1989 cake_id: Some(1),
1990 }
1991 );
1992
1993 assert_eq!(
1994 my_fruit::ActiveModel {
1995 id: Set(1),
1996 name: NotSet,
1997 cake_id: Set(None),
1998 }
1999 .try_into_model(),
2000 Err(DbErr::AttrNotSet(String::from("name")))
2001 );
2002
2003 assert_eq!(
2004 my_fruit::ActiveModel {
2005 id: Set(1),
2006 name: Set("Pineapple".to_owned()),
2007 cake_id: NotSet,
2008 }
2009 .try_into_model(),
2010 Err(DbErr::AttrNotSet(String::from("cake_id")))
2011 );
2012 }
2013
2014 #[test]
2015 #[cfg(feature = "macros")]
2016 fn test_derive_try_into_model_2() {
2017 mod my_fruit {
2018 use crate as sea_orm;
2019 use crate::entity::prelude::*;
2020
2021 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2022 #[sea_orm(table_name = "fruit")]
2023 pub struct Model {
2024 #[sea_orm(primary_key)]
2025 pub id: i32,
2026 pub name: String,
2027 #[sea_orm(ignore)]
2028 pub cake_id: Option<i32>,
2029 }
2030
2031 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2032 pub enum Relation {}
2033
2034 impl ActiveModelBehavior for ActiveModel {}
2035 }
2036 assert_eq!(
2037 my_fruit::ActiveModel {
2038 id: Set(1),
2039 name: Set("Pineapple".to_owned()),
2040 }
2041 .try_into_model()
2042 .unwrap(),
2043 my_fruit::Model {
2044 id: 1,
2045 name: "Pineapple".to_owned(),
2046 cake_id: None,
2047 }
2048 );
2049 }
2050
2051 #[test]
2052 #[cfg(feature = "macros")]
2053 fn test_derive_try_into_model_3() {
2054 mod my_fruit {
2055 use crate as sea_orm;
2056 use crate::entity::prelude::*;
2057
2058 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2059 #[sea_orm(table_name = "fruit")]
2060 pub struct Model {
2061 #[sea_orm(primary_key)]
2062 pub id: i32,
2063 #[sea_orm(ignore)]
2064 pub name: String,
2065 pub cake_id: Option<i32>,
2066 }
2067
2068 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2069 pub enum Relation {}
2070
2071 impl ActiveModelBehavior for ActiveModel {}
2072 }
2073 assert_eq!(
2074 my_fruit::ActiveModel {
2075 id: Set(1),
2076 cake_id: Set(Some(1)),
2077 }
2078 .try_into_model()
2079 .unwrap(),
2080 my_fruit::Model {
2081 id: 1,
2082 name: "".to_owned(),
2083 cake_id: Some(1),
2084 }
2085 );
2086 }
2087
2088 #[test]
2089 #[cfg(feature = "with-json")]
2090 fn test_active_model_set_from_json_1() {
2091 assert_eq!(
2092 cake::ActiveModel::from_json(json!({
2093 "id": 1,
2094 "name": "Apple Pie",
2095 }))
2096 .unwrap(),
2097 cake::ActiveModel {
2098 id: Set(1),
2099 name: Set("Apple Pie".to_owned()),
2100 }
2101 );
2102
2103 assert_eq!(
2104 cake::ActiveModel::from_json(json!({
2105 "id": 1,
2106 }))
2107 .unwrap(),
2108 cake::ActiveModel {
2109 id: Set(1),
2110 name: NotSet,
2111 }
2112 );
2113
2114 assert_eq!(
2115 cake::ActiveModel::from_json(json!({
2116 "name": "Apple Pie",
2117 }))
2118 .unwrap(),
2119 cake::ActiveModel {
2120 id: NotSet,
2121 name: Set("Apple Pie".to_owned()),
2122 }
2123 );
2124
2125 let mut cake: cake::ActiveModel = Default::default();
2126 cake.set_from_json(json!({
2127 "name": "Apple Pie",
2128 }))
2129 .unwrap();
2130 assert_eq!(
2131 cake,
2132 cake::ActiveModel {
2133 id: NotSet,
2134 name: Set("Apple Pie".to_owned()),
2135 }
2136 );
2137 }
2138
2139 #[test]
2140 #[cfg(feature = "with-json")]
2141 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
2142 let mut fruit: fruit::ActiveModel = Default::default();
2143
2144 fruit.set_from_json(json!({
2145 "name": "Apple",
2146 }))?;
2147 assert_eq!(
2148 fruit,
2149 fruit::ActiveModel {
2150 id: ActiveValue::NotSet,
2151 name: ActiveValue::Set("Apple".to_owned()),
2152 cake_id: ActiveValue::NotSet,
2153 }
2154 );
2155
2156 assert_eq!(
2157 fruit::ActiveModel::from_json(json!({
2158 "name": "Apple",
2159 }))?,
2160 fruit::ActiveModel {
2161 id: ActiveValue::NotSet,
2162 name: ActiveValue::Set("Apple".to_owned()),
2163 cake_id: ActiveValue::NotSet,
2164 }
2165 );
2166
2167 fruit.set_from_json(json!({
2168 "name": "Apple",
2169 "cake_id": null,
2170 }))?;
2171 assert_eq!(
2172 fruit,
2173 fruit::ActiveModel {
2174 id: ActiveValue::NotSet,
2175 name: ActiveValue::Set("Apple".to_owned()),
2176 cake_id: ActiveValue::Set(None),
2177 }
2178 );
2179
2180 fruit.set_from_json(json!({
2181 "id": null,
2182 "name": "Apple",
2183 "cake_id": 1,
2184 }))?;
2185 assert_eq!(
2186 fruit,
2187 fruit::ActiveModel {
2188 id: ActiveValue::NotSet,
2189 name: ActiveValue::Set("Apple".to_owned()),
2190 cake_id: ActiveValue::Set(Some(1)),
2191 }
2192 );
2193
2194 fruit.set_from_json(json!({
2195 "id": 2,
2196 "name": "Apple",
2197 "cake_id": 1,
2198 }))?;
2199 assert_eq!(
2200 fruit,
2201 fruit::ActiveModel {
2202 id: ActiveValue::NotSet,
2203 name: ActiveValue::Set("Apple".to_owned()),
2204 cake_id: ActiveValue::Set(Some(1)),
2205 }
2206 );
2207
2208 let mut fruit = fruit::ActiveModel {
2209 id: ActiveValue::Set(1),
2210 name: ActiveValue::NotSet,
2211 cake_id: ActiveValue::NotSet,
2212 };
2213 fruit.set_from_json(json!({
2214 "id": 8,
2215 "name": "Apple",
2216 "cake_id": 1,
2217 }))?;
2218 assert_eq!(
2219 fruit,
2220 fruit::ActiveModel {
2221 id: ActiveValue::Set(1),
2222 name: ActiveValue::Set("Apple".to_owned()),
2223 cake_id: ActiveValue::Set(Some(1)),
2224 }
2225 );
2226
2227 Ok(())
2228 }
2229
2230 #[test]
2231 #[cfg(feature = "with-json")]
2232 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
2233 use crate::*;
2234
2235 let db = MockDatabase::new(DbBackend::Postgres)
2236 .append_exec_results([
2237 MockExecResult {
2238 last_insert_id: 1,
2239 rows_affected: 1,
2240 },
2241 MockExecResult {
2242 last_insert_id: 1,
2243 rows_affected: 1,
2244 },
2245 ])
2246 .append_query_results([
2247 [fruit::Model {
2248 id: 1,
2249 name: "Apple".to_owned(),
2250 cake_id: None,
2251 }],
2252 [fruit::Model {
2253 id: 2,
2254 name: "Orange".to_owned(),
2255 cake_id: Some(1),
2256 }],
2257 ])
2258 .into_connection();
2259
2260 let mut fruit: fruit::ActiveModel = Default::default();
2261 fruit.set_from_json(json!({
2262 "name": "Apple",
2263 }))?;
2264 fruit.save(&db)?;
2265
2266 let mut fruit = fruit::ActiveModel {
2267 id: Set(2),
2268 ..Default::default()
2269 };
2270 fruit.set_from_json(json!({
2271 "id": 9,
2272 "name": "Orange",
2273 "cake_id": 1,
2274 }))?;
2275 fruit.save(&db)?;
2276
2277 assert_eq!(
2278 db.into_transaction_log(),
2279 [
2280 Transaction::from_sql_and_values(
2281 DbBackend::Postgres,
2282 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
2283 ["Apple".into()],
2284 ),
2285 Transaction::from_sql_and_values(
2286 DbBackend::Postgres,
2287 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2288 ["Orange".into(), 1i32.into(), 2i32.into()],
2289 ),
2290 ]
2291 );
2292
2293 Ok(())
2294 }
2295
2296 #[test]
2297 fn test_active_model_is_changed() {
2298 let mut fruit: fruit::ActiveModel = Default::default();
2299 assert!(!fruit.is_changed());
2300
2301 fruit.set(fruit::Column::Name, "apple".into());
2302 assert!(fruit.is_changed());
2303
2304 let mut fruit = fruit::Model {
2305 id: 1,
2306 name: "".into(),
2307 cake_id: None,
2308 };
2309 fruit.set("name".parse().unwrap(), "orange".into());
2310 assert_eq!(fruit.name, "orange");
2311 }
2312
2313 #[test]
2314 fn test_reset_1() {
2315 assert_eq!(
2316 fruit::Model {
2317 id: 1,
2318 name: "Apple".into(),
2319 cake_id: None,
2320 }
2321 .into_active_model(),
2322 fruit::ActiveModel {
2323 id: Unchanged(1),
2324 name: Unchanged("Apple".into()),
2325 cake_id: Unchanged(None)
2326 },
2327 );
2328
2329 assert_eq!(
2330 fruit::Model {
2331 id: 1,
2332 name: "Apple".into(),
2333 cake_id: None,
2334 }
2335 .into_active_model()
2336 .reset_all(),
2337 fruit::ActiveModel {
2338 id: Set(1),
2339 name: Set("Apple".into()),
2340 cake_id: Set(None)
2341 },
2342 );
2343
2344 assert_eq!(
2345 fruit::Model {
2346 id: 1,
2347 name: "Apple".into(),
2348 cake_id: Some(2),
2349 }
2350 .into_active_model(),
2351 fruit::ActiveModel {
2352 id: Unchanged(1),
2353 name: Unchanged("Apple".into()),
2354 cake_id: Unchanged(Some(2)),
2355 },
2356 );
2357
2358 assert_eq!(
2359 fruit::Model {
2360 id: 1,
2361 name: "Apple".into(),
2362 cake_id: Some(2),
2363 }
2364 .into_active_model()
2365 .reset_all(),
2366 fruit::ActiveModel {
2367 id: Set(1),
2368 name: Set("Apple".into()),
2369 cake_id: Set(Some(2)),
2370 },
2371 );
2372 }
2373
2374 #[test]
2375 fn test_reset_2() -> Result<(), DbErr> {
2376 use crate::*;
2377
2378 let db = MockDatabase::new(DbBackend::Postgres)
2379 .append_exec_results(vec![
2380 MockExecResult {
2381 last_insert_id: 1,
2382 rows_affected: 1,
2383 },
2384 MockExecResult {
2385 last_insert_id: 1,
2386 rows_affected: 1,
2387 },
2388 ])
2389 .append_query_results(vec![
2390 vec![fruit::Model {
2391 id: 1,
2392 name: "Apple".to_owned(),
2393 cake_id: None,
2394 }],
2395 vec![fruit::Model {
2396 id: 1,
2397 name: "Apple".to_owned(),
2398 cake_id: None,
2399 }],
2400 ])
2401 .into_connection();
2402
2403 fruit::Model {
2404 id: 1,
2405 name: "Apple".into(),
2406 cake_id: None,
2407 }
2408 .into_active_model()
2409 .update(&db)?;
2410
2411 fruit::Model {
2412 id: 1,
2413 name: "Apple".into(),
2414 cake_id: None,
2415 }
2416 .into_active_model()
2417 .reset_all()
2418 .update(&db)?;
2419
2420 assert_eq!(
2421 db.into_transaction_log(),
2422 vec![
2423 Transaction::from_sql_and_values(
2424 DbBackend::Postgres,
2425 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
2426 vec![1i32.into(), 1u64.into()],
2427 ),
2428 Transaction::from_sql_and_values(
2429 DbBackend::Postgres,
2430 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2431 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
2432 ),
2433 ]
2434 );
2435
2436 Ok(())
2437 }
2438
2439 #[test]
2440 fn test_active_model_default_values() {
2441 assert_eq!(
2442 fruit::ActiveModel::default_values(),
2443 fruit::ActiveModel {
2444 id: Set(0),
2445 name: Set("".into()),
2446 cake_id: Set(None),
2447 },
2448 );
2449
2450 assert_eq!(
2451 lunch_set::ActiveModel::default_values(),
2452 lunch_set::ActiveModel {
2453 id: Set(0),
2454 name: Set("".into()),
2455 tea: NotSet,
2456 },
2457 );
2458 }
2459
2460 #[test]
2461 fn test_active_model_set_parent_key() {
2462 let mut fruit = fruit::Model {
2463 id: 2,
2464 name: "F".into(),
2465 cake_id: None,
2466 }
2467 .into_active_model();
2468
2469 let cake = cake::Model {
2470 id: 4,
2471 name: "C".into(),
2472 }
2473 .into_active_model();
2474
2475 fruit.set_parent_key(&cake).unwrap();
2476
2477 assert_eq!(
2478 fruit,
2479 fruit::ActiveModel {
2480 id: Unchanged(2),
2481 name: Unchanged("F".into()),
2482 cake_id: Set(Some(4)),
2483 }
2484 );
2485
2486 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
2487
2488 assert_eq!(
2489 fruit,
2490 fruit::ActiveModel {
2491 id: Unchanged(2),
2492 name: Unchanged("F".into()),
2493 cake_id: Set(None),
2494 }
2495 );
2496
2497 let mut cake_filling = cake_filling::ActiveModel::new();
2498
2499 cake_filling.set_parent_key(&cake).unwrap();
2500
2501 assert_eq!(
2502 cake_filling,
2503 cake_filling::ActiveModel {
2504 cake_id: Set(4),
2505 filling_id: NotSet,
2506 }
2507 );
2508 }
2509}