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 fn is_changed(&self) -> bool {
525 <Self::Entity as EntityTrait>::Column::iter()
526 .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
527 }
528
529 #[doc(hidden)]
530 fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
532 where
533 R: EntityTrait,
534 AM: ActiveModelTrait<Entity = R>,
535 Self::Entity: Related<R>,
536 {
537 let rel_def = Self::Entity::to();
538
539 if rel_def.is_owner {
540 return Err(DbErr::Type(format!(
541 "Relation from {} to {} is not belongs_to",
542 <Self::Entity as Default>::default().as_str(),
543 <R as Default>::default().as_str()
544 )));
545 }
546
547 let values = get_key_from_active_model(&rel_def.to_col, model)?;
548
549 set_key_on_active_model(&rel_def.from_col, self, values)?;
550
551 Ok(())
552 }
553
554 #[doc(hidden)]
555 fn set_parent_key_for<R, AM>(
556 &mut self,
557 model: &AM,
558 rel: <Self::Entity as EntityTrait>::Relation,
559 ) -> Result<(), DbErr>
560 where
561 R: EntityTrait,
562 AM: ActiveModelTrait<Entity = R>,
563 {
564 let rel_def = rel.def();
565
566 if rel_def.is_owner {
567 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
568 }
569
570 let values = get_key_from_active_model(&rel_def.to_col, model)?;
571
572 set_key_on_active_model(&rel_def.from_col, self, values)?;
573
574 Ok(())
575 }
576
577 #[doc(hidden)]
578 fn set_parent_key_for_def<R, AM>(
579 &mut self,
580 model: &AM,
581 rel_def: &RelationDef,
582 ) -> Result<(), DbErr>
583 where
584 R: EntityTrait,
585 AM: ActiveModelTrait<Entity = R>,
586 {
587 if rel_def.is_owner {
588 return Err(DbErr::Type(format!(
589 "Relation {rel_def:?} is not belongs_to"
590 )));
591 }
592
593 let values = get_key_from_active_model(&rel_def.to_col, model)?;
594
595 set_key_on_active_model(&rel_def.from_col, self, values)?;
596
597 Ok(())
598 }
599
600 #[doc(hidden)]
601 fn set_parent_key_for_self_rev<AM>(
602 &mut self,
603 model: &AM,
604 rel: <Self::Entity as EntityTrait>::Relation,
605 ) -> Result<(), DbErr>
606 where
607 AM: ActiveModelTrait<Entity = Self::Entity>,
608 {
609 let rel_def = rel.def();
610
611 if !rel_def.is_owner {
612 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
613 }
614
615 let values = get_key_from_active_model(&rel_def.from_col, model)?;
616
617 set_key_on_active_model(&rel_def.to_col, self, values)?;
618
619 Ok(())
620 }
621
622 #[doc(hidden)]
623 fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
625 where
626 R: EntityTrait,
627 Self::Entity: Related<R>,
628 {
629 let rel_def = Self::Entity::to();
630
631 if rel_def.is_owner {
632 return Err(DbErr::Type(format!(
633 "Relation from {} to {} is not belongs_to",
634 <Self::Entity as Default>::default().as_str(),
635 <R as Default>::default().as_str()
636 )));
637 }
638
639 clear_key_on_active_model(&rel_def.from_col, self)
640 }
641
642 #[doc(hidden)]
643 fn clear_parent_key_for_self_rev(
644 &mut self,
645 rel: <Self::Entity as EntityTrait>::Relation,
646 ) -> Result<bool, DbErr> {
647 let rel_def = rel.def();
648
649 if !rel_def.is_owner {
650 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
651 }
652
653 clear_key_on_active_model(&rel_def.to_col, self)
654 }
655
656 #[doc(hidden)]
657 fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
659 where
660 R: EntityTrait,
661 Self::Entity: Related<R>,
662 {
663 let rel_def = Self::Entity::to();
664
665 if rel_def.is_owner {
666 return Err(DbErr::Type(format!(
667 "Relation from {} to {} is not belongs_to",
668 <Self::Entity as Default>::default().as_str(),
669 <R as Default>::default().as_str()
670 )));
671 }
672
673 get_key_from_active_model(&rel_def.from_col, self)
674 }
675
676 #[doc(hidden)]
677 fn get_parent_key_for(
679 &self,
680 rel: <Self::Entity as EntityTrait>::Relation,
681 ) -> Result<ValueTuple, DbErr> {
682 let rel_def = rel.def();
683
684 if rel_def.is_owner {
685 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
686 }
687
688 get_key_from_active_model(&rel_def.from_col, self)
689 }
690
691 #[doc(hidden)]
692 fn find_belongs_to_self(
693 &self,
694 rel: <Self::Entity as EntityTrait>::Relation,
695 ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
696 let rel_def = rel.def();
697
698 if !rel_def.is_owner {
699 return Err(DbErr::Type(format!(
700 "Relation {rel:?} is not has_one / has_many"
701 )));
702 }
703
704 let id = get_key_from_active_model(&rel_def.from_col, self)?;
705
706 Ok(Self::Entity::find().filter(
707 column_tuple_in_condition(
708 &<Self::Entity as Default>::default().table_ref(),
709 &rel_def.to_col,
710 &[id],
711 DbBackend::Sqlite,
712 )
713 .expect(""),
714 ))
715 }
716
717 #[doc(hidden)]
718 fn find_belongs_to_model<AM>(
719 rel_def: &RelationDef,
720 belongs_to: &AM,
721 ) -> Result<crate::query::Select<Self::Entity>, DbErr>
722 where
723 AM: ActiveModelTrait,
724 {
725 if rel_def.is_owner {
726 return Err(DbErr::Type(format!(
727 "Relation {rel_def:?} is not belongs_to"
728 )));
729 }
730
731 let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
732 Ok(<Self::Entity as EntityTrait>::find().filter(
733 column_tuple_in_condition(
734 &rel_def.from_tbl,
735 &rel_def.from_col,
736 &[id],
737 DbBackend::Sqlite,
738 )
739 .expect(""),
740 ))
741 }
742
743 fn find_related<R>(&self, _: R) -> crate::query::Select<R>
745 where
746 R: EntityTrait,
747 Self::Entity: Related<R>,
748 {
749 Self::Entity::find_related().belongs_to_active_model(self)
750 }
751
752 #[doc(hidden)]
753 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
754 where
755 AM: ActiveModelTrait,
756 Self::Entity: Related<AM::Entity>,
757 {
758 self.find_related(AM::Entity::default())
759 }
760
761 #[doc(hidden)]
764 fn establish_links<J, R, RM, C>(
765 &self,
766 _: J,
767 related_models: &[RM],
768 delete_leftover: bool,
769 db: &C,
770 ) -> Result<(), DbErr>
771 where
772 R: EntityTrait,
773 RM: ActiveModelTrait<Entity = R>,
774 J: EntityTrait + Related<R> + Related<Self::Entity>,
775 J::Model: IntoActiveModel<J::ActiveModel>,
776 J::ActiveModel: ActiveModelBehavior,
777 C: ConnectionTrait,
778 {
779 let left = <J as Related<Self::Entity>>::to();
780 let right = <J as Related<R>>::to();
781
782 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
783 }
784
785 #[doc(hidden)]
786 fn establish_links_self<J, RM, C>(
787 &self,
788 _: J,
789 related_models: &[RM],
790 delete_leftover: bool,
791 db: &C,
792 ) -> Result<(), DbErr>
793 where
794 RM: ActiveModelTrait<Entity = Self::Entity>,
795 J: EntityTrait,
796 J::Model: IntoActiveModel<J::ActiveModel>,
797 J::ActiveModel: ActiveModelBehavior,
798 C: ConnectionTrait,
799 Self::Entity: RelatedSelfVia<J>,
800 {
801 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
802 let right = <Self::Entity as RelatedSelfVia<J>>::to();
803
804 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
805 }
806
807 #[doc(hidden)]
808 fn establish_links_self_rev<J, RM, C>(
809 &self,
810 _: J,
811 related_models: &[RM],
812 delete_leftover: bool,
813 db: &C,
814 ) -> Result<(), DbErr>
815 where
816 RM: ActiveModelTrait<Entity = Self::Entity>,
817 J: EntityTrait,
818 J::Model: IntoActiveModel<J::ActiveModel>,
819 J::ActiveModel: ActiveModelBehavior,
820 C: ConnectionTrait,
821 Self::Entity: RelatedSelfVia<J>,
822 {
823 let left = <Self::Entity as RelatedSelfVia<J>>::to();
824 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
825
826 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
827 }
828
829 #[doc(hidden)]
830 fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
831 where
832 J: EntityTrait + Related<Self::Entity>,
833 C: ConnectionTrait,
834 {
835 let rel_def = <J as Related<Self::Entity>>::to();
836 let id = get_key_from_active_model(&rel_def.to_col, self)?;
837
838 J::delete_many()
839 .filter(
840 column_tuple_in_condition(
841 &rel_def.from_tbl,
842 &rel_def.from_col,
843 &[id],
844 DbBackend::Sqlite,
845 )
846 .expect(""),
847 )
848 .exec(db)
849 }
850
851 #[doc(hidden)]
852 fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
853 where
854 J: EntityTrait,
855 C: ConnectionTrait,
856 Self::Entity: RelatedSelfVia<J>,
857 {
858 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
859 let right = <Self::Entity as RelatedSelfVia<J>>::to();
860
861 let id = get_key_from_active_model(&left.to_col, self)?;
862
863 if left.to_col != right.to_col {
864 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
865 }
866
867 J::delete_many()
868 .filter(
869 Condition::any()
870 .add(
871 column_tuple_in_condition(
872 &left.from_tbl,
873 &left.from_col,
874 std::slice::from_ref(&id),
875 DbBackend::Sqlite,
876 )
877 .expect(""),
878 )
879 .add(
880 column_tuple_in_condition(
881 &right.from_tbl,
882 &right.from_col,
883 std::slice::from_ref(&id),
884 DbBackend::Sqlite,
885 )
886 .expect(""),
887 ),
888 )
889 .exec(db)
890 }
891}
892
893#[allow(unused_variables)]
921pub trait ActiveModelBehavior: ActiveModelTrait {
922 fn new() -> Self {
935 <Self as ActiveModelTrait>::default()
936 }
937
938 fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
940 where
941 C: ConnectionTrait,
942 {
943 Ok(self)
944 }
945
946 fn after_save<C>(
948 model: <Self::Entity as EntityTrait>::Model,
949 db: &C,
950 insert: bool,
951 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
952 where
953 C: ConnectionTrait,
954 {
955 Ok(model)
956 }
957
958 fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
960 where
961 C: ConnectionTrait,
962 {
963 Ok(self)
964 }
965
966 fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
968 where
969 C: ConnectionTrait,
970 {
971 Ok(self)
972 }
973}
974
975pub trait IntoActiveModel<A>
977where
978 A: ActiveModelTrait,
979{
980 fn into_active_model(self) -> A;
982}
983
984impl<A> IntoActiveModel<A> for A
985where
986 A: ActiveModelTrait,
987{
988 fn into_active_model(self) -> A {
989 self
990 }
991}
992
993fn establish_links<EM, J, RM, C>(
994 model: &EM,
995 related_models: &[RM],
996 left: RelationDef,
997 right: RelationDef,
998 delete_leftover: bool,
999 db: &C,
1000) -> Result<(), DbErr>
1001where
1002 EM: ActiveModelTrait,
1003 RM: ActiveModelTrait,
1004 J: EntityTrait,
1005 J::Model: IntoActiveModel<J::ActiveModel>,
1006 J::ActiveModel: ActiveModelBehavior,
1007 C: ConnectionTrait,
1008{
1009 let mut require_leftover = true;
1010
1011 if related_models.is_empty() {
1012 require_leftover = false;
1014 }
1015
1016 let primary_key = J::primary_key_identity();
1017 if require_leftover
1018 && primary_key.fully_contains(&left.from_col)
1019 && primary_key.fully_contains(&right.from_col)
1020 {
1021 require_leftover = false;
1024 }
1025
1026 let mut leftover = Vec::new();
1027 if delete_leftover || require_leftover {
1028 for item in
1029 <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(&left, model)?.all(db)?
1030 {
1031 let item = item.into_active_model();
1032 let key = get_key_from_active_model(&right.from_col, &item)?;
1033 leftover.push((item, key));
1034 }
1035 }
1036 let leftover = leftover; let mut via_models = Vec::new();
1039 let mut all_keys = std::collections::HashSet::new();
1040
1041 for related_model in related_models {
1042 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1043 via.set_parent_key_for_def(model, &left)?;
1044 via.set_parent_key_for_def(related_model, &right)?;
1045 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1046 if !leftover.iter().any(|t| t.1 == via_key) {
1047 via_models.push(via);
1049 }
1050 if delete_leftover {
1051 all_keys.insert(via_key);
1052 }
1053 }
1054
1055 if delete_leftover {
1056 let mut to_delete = Vec::new();
1057 for (leftover, key) in leftover {
1058 if !all_keys.contains(&key) {
1059 to_delete.push(
1060 leftover
1061 .get_primary_key_value()
1062 .expect("item is a full model"),
1063 );
1064 }
1065 }
1066 if !to_delete.is_empty() {
1067 J::delete_many()
1068 .filter_by_value_tuples(&to_delete)
1069 .exec(db)?;
1070 }
1071 }
1072
1073 if !via_models.is_empty() {
1074 J::insert_many(via_models)
1076 .on_conflict_do_nothing()
1077 .exec(db)?;
1078 }
1079
1080 Ok(())
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085 use crate::{DbErr, entity::*, tests_cfg::*};
1086 use pretty_assertions::assert_eq;
1087
1088 #[cfg(feature = "with-json")]
1089 use serde_json::json;
1090
1091 #[test]
1092 #[cfg(feature = "macros")]
1093 fn test_derive_into_active_model_1() {
1094 mod my_fruit {
1095 pub use super::fruit::*;
1096 use crate as sea_orm;
1097 use crate::entity::prelude::*;
1098
1099 #[derive(DeriveIntoActiveModel)]
1100 pub struct NewFruit {
1101 pub name: String,
1103 pub cake_id: i32,
1105 }
1106 }
1107
1108 assert_eq!(
1109 my_fruit::NewFruit {
1110 name: "Apple".to_owned(),
1111 cake_id: 1,
1112 }
1113 .into_active_model(),
1114 fruit::ActiveModel {
1115 id: NotSet,
1116 name: Set("Apple".to_owned()),
1117 cake_id: Set(Some(1)),
1118 }
1119 );
1120 }
1121
1122 #[test]
1123 #[cfg(feature = "macros")]
1124 fn test_derive_into_active_model_2() {
1125 use crate as sea_orm;
1126 use crate::entity::prelude::*;
1127
1128 #[derive(DeriveIntoActiveModel)]
1129 #[sea_orm(active_model = "fruit::ActiveModel")]
1130 struct FruitName {
1131 name: String,
1132 }
1133
1134 assert_eq!(
1135 FruitName {
1136 name: "Apple Pie".to_owned(),
1137 }
1138 .into_active_model(),
1139 fruit::ActiveModel {
1140 id: NotSet,
1141 name: Set("Apple Pie".to_owned()),
1142 cake_id: NotSet,
1143 }
1144 );
1145
1146 #[derive(DeriveIntoActiveModel)]
1147 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1148 struct FruitCake {
1149 cake_id: Option<Option<i32>>,
1150 }
1151
1152 assert_eq!(
1153 FruitCake {
1154 cake_id: Some(Some(1)),
1155 }
1156 .into_active_model(),
1157 fruit::ActiveModel {
1158 id: NotSet,
1159 name: NotSet,
1160 cake_id: Set(Some(1)),
1161 }
1162 );
1163
1164 assert_eq!(
1165 FruitCake {
1166 cake_id: Some(None),
1167 }
1168 .into_active_model(),
1169 fruit::ActiveModel {
1170 id: NotSet,
1171 name: NotSet,
1172 cake_id: Set(None),
1173 }
1174 );
1175
1176 assert_eq!(
1177 FruitCake { cake_id: None }.into_active_model(),
1178 fruit::ActiveModel {
1179 id: NotSet,
1180 name: NotSet,
1181 cake_id: NotSet,
1182 }
1183 );
1184 }
1185
1186 #[test]
1187 #[cfg(feature = "macros")]
1188 fn test_derive_try_into_model_1() {
1189 mod my_fruit {
1190 use crate as sea_orm;
1191 use crate::entity::prelude::*;
1192
1193 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1194 #[sea_orm(table_name = "fruit")]
1195 pub struct Model {
1196 #[sea_orm(primary_key)]
1197 pub id: i32,
1198 pub name: String,
1199 pub cake_id: Option<i32>,
1200 }
1201
1202 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1203 pub enum Relation {}
1204
1205 impl ActiveModelBehavior for ActiveModel {}
1206 }
1207 assert_eq!(
1208 my_fruit::ActiveModel {
1209 id: Set(1),
1210 name: Set("Pineapple".to_owned()),
1211 cake_id: Set(None),
1212 }
1213 .try_into_model()
1214 .unwrap(),
1215 my_fruit::Model {
1216 id: 1,
1217 name: "Pineapple".to_owned(),
1218 cake_id: None,
1219 }
1220 );
1221
1222 assert_eq!(
1223 my_fruit::ActiveModel {
1224 id: Set(2),
1225 name: Set("Apple".to_owned()),
1226 cake_id: Set(Some(1)),
1227 }
1228 .try_into_model()
1229 .unwrap(),
1230 my_fruit::Model {
1231 id: 2,
1232 name: "Apple".to_owned(),
1233 cake_id: Some(1),
1234 }
1235 );
1236
1237 assert_eq!(
1238 my_fruit::ActiveModel {
1239 id: Set(1),
1240 name: NotSet,
1241 cake_id: Set(None),
1242 }
1243 .try_into_model(),
1244 Err(DbErr::AttrNotSet(String::from("name")))
1245 );
1246
1247 assert_eq!(
1248 my_fruit::ActiveModel {
1249 id: Set(1),
1250 name: Set("Pineapple".to_owned()),
1251 cake_id: NotSet,
1252 }
1253 .try_into_model(),
1254 Err(DbErr::AttrNotSet(String::from("cake_id")))
1255 );
1256 }
1257
1258 #[test]
1259 #[cfg(feature = "macros")]
1260 fn test_derive_try_into_model_2() {
1261 mod my_fruit {
1262 use crate as sea_orm;
1263 use crate::entity::prelude::*;
1264
1265 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1266 #[sea_orm(table_name = "fruit")]
1267 pub struct Model {
1268 #[sea_orm(primary_key)]
1269 pub id: i32,
1270 pub name: String,
1271 #[sea_orm(ignore)]
1272 pub cake_id: Option<i32>,
1273 }
1274
1275 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1276 pub enum Relation {}
1277
1278 impl ActiveModelBehavior for ActiveModel {}
1279 }
1280 assert_eq!(
1281 my_fruit::ActiveModel {
1282 id: Set(1),
1283 name: Set("Pineapple".to_owned()),
1284 }
1285 .try_into_model()
1286 .unwrap(),
1287 my_fruit::Model {
1288 id: 1,
1289 name: "Pineapple".to_owned(),
1290 cake_id: None,
1291 }
1292 );
1293 }
1294
1295 #[test]
1296 #[cfg(feature = "macros")]
1297 fn test_derive_try_into_model_3() {
1298 mod my_fruit {
1299 use crate as sea_orm;
1300 use crate::entity::prelude::*;
1301
1302 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1303 #[sea_orm(table_name = "fruit")]
1304 pub struct Model {
1305 #[sea_orm(primary_key)]
1306 pub id: i32,
1307 #[sea_orm(ignore)]
1308 pub name: String,
1309 pub cake_id: Option<i32>,
1310 }
1311
1312 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1313 pub enum Relation {}
1314
1315 impl ActiveModelBehavior for ActiveModel {}
1316 }
1317 assert_eq!(
1318 my_fruit::ActiveModel {
1319 id: Set(1),
1320 cake_id: Set(Some(1)),
1321 }
1322 .try_into_model()
1323 .unwrap(),
1324 my_fruit::Model {
1325 id: 1,
1326 name: "".to_owned(),
1327 cake_id: Some(1),
1328 }
1329 );
1330 }
1331
1332 #[test]
1333 #[cfg(feature = "with-json")]
1334 fn test_active_model_set_from_json_1() {
1335 assert_eq!(
1336 cake::ActiveModel::from_json(json!({
1337 "id": 1,
1338 "name": "Apple Pie",
1339 }))
1340 .unwrap(),
1341 cake::ActiveModel {
1342 id: Set(1),
1343 name: Set("Apple Pie".to_owned()),
1344 }
1345 );
1346
1347 assert_eq!(
1348 cake::ActiveModel::from_json(json!({
1349 "id": 1,
1350 }))
1351 .unwrap(),
1352 cake::ActiveModel {
1353 id: Set(1),
1354 name: NotSet,
1355 }
1356 );
1357
1358 assert_eq!(
1359 cake::ActiveModel::from_json(json!({
1360 "name": "Apple Pie",
1361 }))
1362 .unwrap(),
1363 cake::ActiveModel {
1364 id: NotSet,
1365 name: Set("Apple Pie".to_owned()),
1366 }
1367 );
1368
1369 let mut cake: cake::ActiveModel = Default::default();
1370 cake.set_from_json(json!({
1371 "name": "Apple Pie",
1372 }))
1373 .unwrap();
1374 assert_eq!(
1375 cake,
1376 cake::ActiveModel {
1377 id: NotSet,
1378 name: Set("Apple Pie".to_owned()),
1379 }
1380 );
1381 }
1382
1383 #[test]
1384 #[cfg(feature = "with-json")]
1385 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1386 let mut fruit: fruit::ActiveModel = Default::default();
1387
1388 fruit.set_from_json(json!({
1389 "name": "Apple",
1390 }))?;
1391 assert_eq!(
1392 fruit,
1393 fruit::ActiveModel {
1394 id: ActiveValue::NotSet,
1395 name: ActiveValue::Set("Apple".to_owned()),
1396 cake_id: ActiveValue::NotSet,
1397 }
1398 );
1399
1400 assert_eq!(
1401 fruit::ActiveModel::from_json(json!({
1402 "name": "Apple",
1403 }))?,
1404 fruit::ActiveModel {
1405 id: ActiveValue::NotSet,
1406 name: ActiveValue::Set("Apple".to_owned()),
1407 cake_id: ActiveValue::NotSet,
1408 }
1409 );
1410
1411 fruit.set_from_json(json!({
1412 "name": "Apple",
1413 "cake_id": null,
1414 }))?;
1415 assert_eq!(
1416 fruit,
1417 fruit::ActiveModel {
1418 id: ActiveValue::NotSet,
1419 name: ActiveValue::Set("Apple".to_owned()),
1420 cake_id: ActiveValue::Set(None),
1421 }
1422 );
1423
1424 fruit.set_from_json(json!({
1425 "id": null,
1426 "name": "Apple",
1427 "cake_id": 1,
1428 }))?;
1429 assert_eq!(
1430 fruit,
1431 fruit::ActiveModel {
1432 id: ActiveValue::NotSet,
1433 name: ActiveValue::Set("Apple".to_owned()),
1434 cake_id: ActiveValue::Set(Some(1)),
1435 }
1436 );
1437
1438 fruit.set_from_json(json!({
1439 "id": 2,
1440 "name": "Apple",
1441 "cake_id": 1,
1442 }))?;
1443 assert_eq!(
1444 fruit,
1445 fruit::ActiveModel {
1446 id: ActiveValue::NotSet,
1447 name: ActiveValue::Set("Apple".to_owned()),
1448 cake_id: ActiveValue::Set(Some(1)),
1449 }
1450 );
1451
1452 let mut fruit = fruit::ActiveModel {
1453 id: ActiveValue::Set(1),
1454 name: ActiveValue::NotSet,
1455 cake_id: ActiveValue::NotSet,
1456 };
1457 fruit.set_from_json(json!({
1458 "id": 8,
1459 "name": "Apple",
1460 "cake_id": 1,
1461 }))?;
1462 assert_eq!(
1463 fruit,
1464 fruit::ActiveModel {
1465 id: ActiveValue::Set(1),
1466 name: ActiveValue::Set("Apple".to_owned()),
1467 cake_id: ActiveValue::Set(Some(1)),
1468 }
1469 );
1470
1471 Ok(())
1472 }
1473
1474 #[test]
1475 #[cfg(feature = "with-json")]
1476 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1477 use crate::*;
1478
1479 let db = MockDatabase::new(DbBackend::Postgres)
1480 .append_exec_results([
1481 MockExecResult {
1482 last_insert_id: 1,
1483 rows_affected: 1,
1484 },
1485 MockExecResult {
1486 last_insert_id: 1,
1487 rows_affected: 1,
1488 },
1489 ])
1490 .append_query_results([
1491 [fruit::Model {
1492 id: 1,
1493 name: "Apple".to_owned(),
1494 cake_id: None,
1495 }],
1496 [fruit::Model {
1497 id: 2,
1498 name: "Orange".to_owned(),
1499 cake_id: Some(1),
1500 }],
1501 ])
1502 .into_connection();
1503
1504 let mut fruit: fruit::ActiveModel = Default::default();
1505 fruit.set_from_json(json!({
1506 "name": "Apple",
1507 }))?;
1508 fruit.save(&db)?;
1509
1510 let mut fruit = fruit::ActiveModel {
1511 id: Set(2),
1512 ..Default::default()
1513 };
1514 fruit.set_from_json(json!({
1515 "id": 9,
1516 "name": "Orange",
1517 "cake_id": 1,
1518 }))?;
1519 fruit.save(&db)?;
1520
1521 assert_eq!(
1522 db.into_transaction_log(),
1523 [
1524 Transaction::from_sql_and_values(
1525 DbBackend::Postgres,
1526 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1527 ["Apple".into()],
1528 ),
1529 Transaction::from_sql_and_values(
1530 DbBackend::Postgres,
1531 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1532 ["Orange".into(), 1i32.into(), 2i32.into()],
1533 ),
1534 ]
1535 );
1536
1537 Ok(())
1538 }
1539
1540 #[test]
1541 fn test_active_model_is_changed() {
1542 let mut fruit: fruit::ActiveModel = Default::default();
1543 assert!(!fruit.is_changed());
1544
1545 fruit.set(fruit::Column::Name, "apple".into());
1546 assert!(fruit.is_changed());
1547
1548 let mut fruit = fruit::Model {
1549 id: 1,
1550 name: "".into(),
1551 cake_id: None,
1552 };
1553 fruit.set("name".parse().unwrap(), "orange".into());
1554 assert_eq!(fruit.name, "orange");
1555 }
1556
1557 #[test]
1558 fn test_reset_1() {
1559 assert_eq!(
1560 fruit::Model {
1561 id: 1,
1562 name: "Apple".into(),
1563 cake_id: None,
1564 }
1565 .into_active_model(),
1566 fruit::ActiveModel {
1567 id: Unchanged(1),
1568 name: Unchanged("Apple".into()),
1569 cake_id: Unchanged(None)
1570 },
1571 );
1572
1573 assert_eq!(
1574 fruit::Model {
1575 id: 1,
1576 name: "Apple".into(),
1577 cake_id: None,
1578 }
1579 .into_active_model()
1580 .reset_all(),
1581 fruit::ActiveModel {
1582 id: Set(1),
1583 name: Set("Apple".into()),
1584 cake_id: Set(None)
1585 },
1586 );
1587
1588 assert_eq!(
1589 fruit::Model {
1590 id: 1,
1591 name: "Apple".into(),
1592 cake_id: Some(2),
1593 }
1594 .into_active_model(),
1595 fruit::ActiveModel {
1596 id: Unchanged(1),
1597 name: Unchanged("Apple".into()),
1598 cake_id: Unchanged(Some(2)),
1599 },
1600 );
1601
1602 assert_eq!(
1603 fruit::Model {
1604 id: 1,
1605 name: "Apple".into(),
1606 cake_id: Some(2),
1607 }
1608 .into_active_model()
1609 .reset_all(),
1610 fruit::ActiveModel {
1611 id: Set(1),
1612 name: Set("Apple".into()),
1613 cake_id: Set(Some(2)),
1614 },
1615 );
1616 }
1617
1618 #[test]
1619 fn test_reset_2() -> Result<(), DbErr> {
1620 use crate::*;
1621
1622 let db = MockDatabase::new(DbBackend::Postgres)
1623 .append_exec_results(vec![
1624 MockExecResult {
1625 last_insert_id: 1,
1626 rows_affected: 1,
1627 },
1628 MockExecResult {
1629 last_insert_id: 1,
1630 rows_affected: 1,
1631 },
1632 ])
1633 .append_query_results(vec![
1634 vec![fruit::Model {
1635 id: 1,
1636 name: "Apple".to_owned(),
1637 cake_id: None,
1638 }],
1639 vec![fruit::Model {
1640 id: 1,
1641 name: "Apple".to_owned(),
1642 cake_id: None,
1643 }],
1644 ])
1645 .into_connection();
1646
1647 fruit::Model {
1648 id: 1,
1649 name: "Apple".into(),
1650 cake_id: None,
1651 }
1652 .into_active_model()
1653 .update(&db)?;
1654
1655 fruit::Model {
1656 id: 1,
1657 name: "Apple".into(),
1658 cake_id: None,
1659 }
1660 .into_active_model()
1661 .reset_all()
1662 .update(&db)?;
1663
1664 assert_eq!(
1665 db.into_transaction_log(),
1666 vec![
1667 Transaction::from_sql_and_values(
1668 DbBackend::Postgres,
1669 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1670 vec![1i32.into(), 1u64.into()],
1671 ),
1672 Transaction::from_sql_and_values(
1673 DbBackend::Postgres,
1674 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1675 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1676 ),
1677 ]
1678 );
1679
1680 Ok(())
1681 }
1682
1683 #[test]
1684 fn test_active_model_default_values() {
1685 assert_eq!(
1686 fruit::ActiveModel::default_values(),
1687 fruit::ActiveModel {
1688 id: Set(0),
1689 name: Set("".into()),
1690 cake_id: Set(None),
1691 },
1692 );
1693
1694 assert_eq!(
1695 lunch_set::ActiveModel::default_values(),
1696 lunch_set::ActiveModel {
1697 id: Set(0),
1698 name: Set("".into()),
1699 tea: NotSet,
1700 },
1701 );
1702 }
1703
1704 #[test]
1705 fn test_active_model_set_parent_key() {
1706 let mut fruit = fruit::Model {
1707 id: 2,
1708 name: "F".into(),
1709 cake_id: None,
1710 }
1711 .into_active_model();
1712
1713 let cake = cake::Model {
1714 id: 4,
1715 name: "C".into(),
1716 }
1717 .into_active_model();
1718
1719 fruit.set_parent_key(&cake).unwrap();
1720
1721 assert_eq!(
1722 fruit,
1723 fruit::ActiveModel {
1724 id: Unchanged(2),
1725 name: Unchanged("F".into()),
1726 cake_id: Set(Some(4)),
1727 }
1728 );
1729
1730 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1731
1732 assert_eq!(
1733 fruit,
1734 fruit::ActiveModel {
1735 id: Unchanged(2),
1736 name: Unchanged("F".into()),
1737 cake_id: Set(None),
1738 }
1739 );
1740
1741 let mut cake_filling = cake_filling::ActiveModel::new();
1742
1743 cake_filling.set_parent_key(&cake).unwrap();
1744
1745 assert_eq!(
1746 cake_filling,
1747 cake_filling::ActiveModel {
1748 cake_id: Set(4),
1749 filling_id: NotSet,
1750 }
1751 );
1752 }
1753}