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 RequiredFruitName {
1131 name: String,
1132 }
1133
1134 assert_eq!(
1135 RequiredFruitName {
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::ActiveModel")]
1148 struct OptionalFruitName {
1149 name: Option<String>,
1150 }
1151
1152 assert_eq!(
1153 OptionalFruitName {
1154 name: Some("Apple Pie".to_owned()),
1155 }
1156 .into_active_model(),
1157 fruit::ActiveModel {
1158 id: NotSet,
1159 name: Set("Apple Pie".to_owned()),
1160 cake_id: NotSet,
1161 }
1162 );
1163
1164 assert_eq!(
1165 OptionalFruitName { name: None }.into_active_model(),
1166 fruit::ActiveModel {
1167 id: NotSet,
1168 name: NotSet,
1169 cake_id: NotSet,
1170 }
1171 );
1172
1173 #[derive(DeriveIntoActiveModel)]
1174 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1175 struct RequiredAndNotNullFruitCake {
1176 cake_id: i32,
1177 }
1178
1179 assert_eq!(
1180 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1181 fruit::ActiveModel {
1182 id: NotSet,
1183 name: NotSet,
1184 cake_id: Set(Some(1)),
1185 }
1186 );
1187
1188 #[derive(DeriveIntoActiveModel)]
1189 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1190 struct OptionalAndNotNullFruitCake {
1191 cake_id: Option<i32>,
1192 }
1193
1194 assert_eq!(
1195 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1196 fruit::ActiveModel {
1197 id: NotSet,
1198 name: NotSet,
1199 cake_id: Set(Some(1)),
1200 }
1201 );
1202
1203 assert_eq!(
1204 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1205 fruit::ActiveModel {
1206 id: NotSet,
1207 name: NotSet,
1208 cake_id: NotSet,
1209 }
1210 );
1211
1212 #[derive(DeriveIntoActiveModel)]
1213 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1214 struct OptionalAndNullableFruitCake {
1215 cake_id: Option<Option<i32>>,
1216 }
1217
1218 assert_eq!(
1219 OptionalAndNullableFruitCake {
1220 cake_id: Some(Some(1)),
1221 }
1222 .into_active_model(),
1223 fruit::ActiveModel {
1224 id: NotSet,
1225 name: NotSet,
1226 cake_id: Set(Some(1)),
1227 }
1228 );
1229
1230 assert_eq!(
1231 OptionalAndNullableFruitCake {
1232 cake_id: Some(None),
1233 }
1234 .into_active_model(),
1235 fruit::ActiveModel {
1236 id: NotSet,
1237 name: NotSet,
1238 cake_id: Set(None),
1239 }
1240 );
1241
1242 assert_eq!(
1243 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1244 fruit::ActiveModel {
1245 id: NotSet,
1246 name: NotSet,
1247 cake_id: NotSet,
1248 }
1249 );
1250 }
1251
1252 #[test]
1253 #[cfg(feature = "macros")]
1254 fn test_derive_try_into_model_1() {
1255 mod my_fruit {
1256 use crate as sea_orm;
1257 use crate::entity::prelude::*;
1258
1259 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1260 #[sea_orm(table_name = "fruit")]
1261 pub struct Model {
1262 #[sea_orm(primary_key)]
1263 pub id: i32,
1264 pub name: String,
1265 pub cake_id: Option<i32>,
1266 }
1267
1268 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1269 pub enum Relation {}
1270
1271 impl ActiveModelBehavior for ActiveModel {}
1272 }
1273 assert_eq!(
1274 my_fruit::ActiveModel {
1275 id: Set(1),
1276 name: Set("Pineapple".to_owned()),
1277 cake_id: Set(None),
1278 }
1279 .try_into_model()
1280 .unwrap(),
1281 my_fruit::Model {
1282 id: 1,
1283 name: "Pineapple".to_owned(),
1284 cake_id: None,
1285 }
1286 );
1287
1288 assert_eq!(
1289 my_fruit::ActiveModel {
1290 id: Set(2),
1291 name: Set("Apple".to_owned()),
1292 cake_id: Set(Some(1)),
1293 }
1294 .try_into_model()
1295 .unwrap(),
1296 my_fruit::Model {
1297 id: 2,
1298 name: "Apple".to_owned(),
1299 cake_id: Some(1),
1300 }
1301 );
1302
1303 assert_eq!(
1304 my_fruit::ActiveModel {
1305 id: Set(1),
1306 name: NotSet,
1307 cake_id: Set(None),
1308 }
1309 .try_into_model(),
1310 Err(DbErr::AttrNotSet(String::from("name")))
1311 );
1312
1313 assert_eq!(
1314 my_fruit::ActiveModel {
1315 id: Set(1),
1316 name: Set("Pineapple".to_owned()),
1317 cake_id: NotSet,
1318 }
1319 .try_into_model(),
1320 Err(DbErr::AttrNotSet(String::from("cake_id")))
1321 );
1322 }
1323
1324 #[test]
1325 #[cfg(feature = "macros")]
1326 fn test_derive_try_into_model_2() {
1327 mod my_fruit {
1328 use crate as sea_orm;
1329 use crate::entity::prelude::*;
1330
1331 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1332 #[sea_orm(table_name = "fruit")]
1333 pub struct Model {
1334 #[sea_orm(primary_key)]
1335 pub id: i32,
1336 pub name: String,
1337 #[sea_orm(ignore)]
1338 pub cake_id: Option<i32>,
1339 }
1340
1341 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1342 pub enum Relation {}
1343
1344 impl ActiveModelBehavior for ActiveModel {}
1345 }
1346 assert_eq!(
1347 my_fruit::ActiveModel {
1348 id: Set(1),
1349 name: Set("Pineapple".to_owned()),
1350 }
1351 .try_into_model()
1352 .unwrap(),
1353 my_fruit::Model {
1354 id: 1,
1355 name: "Pineapple".to_owned(),
1356 cake_id: None,
1357 }
1358 );
1359 }
1360
1361 #[test]
1362 #[cfg(feature = "macros")]
1363 fn test_derive_try_into_model_3() {
1364 mod my_fruit {
1365 use crate as sea_orm;
1366 use crate::entity::prelude::*;
1367
1368 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1369 #[sea_orm(table_name = "fruit")]
1370 pub struct Model {
1371 #[sea_orm(primary_key)]
1372 pub id: i32,
1373 #[sea_orm(ignore)]
1374 pub name: String,
1375 pub cake_id: Option<i32>,
1376 }
1377
1378 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1379 pub enum Relation {}
1380
1381 impl ActiveModelBehavior for ActiveModel {}
1382 }
1383 assert_eq!(
1384 my_fruit::ActiveModel {
1385 id: Set(1),
1386 cake_id: Set(Some(1)),
1387 }
1388 .try_into_model()
1389 .unwrap(),
1390 my_fruit::Model {
1391 id: 1,
1392 name: "".to_owned(),
1393 cake_id: Some(1),
1394 }
1395 );
1396 }
1397
1398 #[test]
1399 #[cfg(feature = "with-json")]
1400 fn test_active_model_set_from_json_1() {
1401 assert_eq!(
1402 cake::ActiveModel::from_json(json!({
1403 "id": 1,
1404 "name": "Apple Pie",
1405 }))
1406 .unwrap(),
1407 cake::ActiveModel {
1408 id: Set(1),
1409 name: Set("Apple Pie".to_owned()),
1410 }
1411 );
1412
1413 assert_eq!(
1414 cake::ActiveModel::from_json(json!({
1415 "id": 1,
1416 }))
1417 .unwrap(),
1418 cake::ActiveModel {
1419 id: Set(1),
1420 name: NotSet,
1421 }
1422 );
1423
1424 assert_eq!(
1425 cake::ActiveModel::from_json(json!({
1426 "name": "Apple Pie",
1427 }))
1428 .unwrap(),
1429 cake::ActiveModel {
1430 id: NotSet,
1431 name: Set("Apple Pie".to_owned()),
1432 }
1433 );
1434
1435 let mut cake: cake::ActiveModel = Default::default();
1436 cake.set_from_json(json!({
1437 "name": "Apple Pie",
1438 }))
1439 .unwrap();
1440 assert_eq!(
1441 cake,
1442 cake::ActiveModel {
1443 id: NotSet,
1444 name: Set("Apple Pie".to_owned()),
1445 }
1446 );
1447 }
1448
1449 #[test]
1450 #[cfg(feature = "with-json")]
1451 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1452 let mut fruit: fruit::ActiveModel = Default::default();
1453
1454 fruit.set_from_json(json!({
1455 "name": "Apple",
1456 }))?;
1457 assert_eq!(
1458 fruit,
1459 fruit::ActiveModel {
1460 id: ActiveValue::NotSet,
1461 name: ActiveValue::Set("Apple".to_owned()),
1462 cake_id: ActiveValue::NotSet,
1463 }
1464 );
1465
1466 assert_eq!(
1467 fruit::ActiveModel::from_json(json!({
1468 "name": "Apple",
1469 }))?,
1470 fruit::ActiveModel {
1471 id: ActiveValue::NotSet,
1472 name: ActiveValue::Set("Apple".to_owned()),
1473 cake_id: ActiveValue::NotSet,
1474 }
1475 );
1476
1477 fruit.set_from_json(json!({
1478 "name": "Apple",
1479 "cake_id": null,
1480 }))?;
1481 assert_eq!(
1482 fruit,
1483 fruit::ActiveModel {
1484 id: ActiveValue::NotSet,
1485 name: ActiveValue::Set("Apple".to_owned()),
1486 cake_id: ActiveValue::Set(None),
1487 }
1488 );
1489
1490 fruit.set_from_json(json!({
1491 "id": null,
1492 "name": "Apple",
1493 "cake_id": 1,
1494 }))?;
1495 assert_eq!(
1496 fruit,
1497 fruit::ActiveModel {
1498 id: ActiveValue::NotSet,
1499 name: ActiveValue::Set("Apple".to_owned()),
1500 cake_id: ActiveValue::Set(Some(1)),
1501 }
1502 );
1503
1504 fruit.set_from_json(json!({
1505 "id": 2,
1506 "name": "Apple",
1507 "cake_id": 1,
1508 }))?;
1509 assert_eq!(
1510 fruit,
1511 fruit::ActiveModel {
1512 id: ActiveValue::NotSet,
1513 name: ActiveValue::Set("Apple".to_owned()),
1514 cake_id: ActiveValue::Set(Some(1)),
1515 }
1516 );
1517
1518 let mut fruit = fruit::ActiveModel {
1519 id: ActiveValue::Set(1),
1520 name: ActiveValue::NotSet,
1521 cake_id: ActiveValue::NotSet,
1522 };
1523 fruit.set_from_json(json!({
1524 "id": 8,
1525 "name": "Apple",
1526 "cake_id": 1,
1527 }))?;
1528 assert_eq!(
1529 fruit,
1530 fruit::ActiveModel {
1531 id: ActiveValue::Set(1),
1532 name: ActiveValue::Set("Apple".to_owned()),
1533 cake_id: ActiveValue::Set(Some(1)),
1534 }
1535 );
1536
1537 Ok(())
1538 }
1539
1540 #[test]
1541 #[cfg(feature = "with-json")]
1542 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1543 use crate::*;
1544
1545 let db = MockDatabase::new(DbBackend::Postgres)
1546 .append_exec_results([
1547 MockExecResult {
1548 last_insert_id: 1,
1549 rows_affected: 1,
1550 },
1551 MockExecResult {
1552 last_insert_id: 1,
1553 rows_affected: 1,
1554 },
1555 ])
1556 .append_query_results([
1557 [fruit::Model {
1558 id: 1,
1559 name: "Apple".to_owned(),
1560 cake_id: None,
1561 }],
1562 [fruit::Model {
1563 id: 2,
1564 name: "Orange".to_owned(),
1565 cake_id: Some(1),
1566 }],
1567 ])
1568 .into_connection();
1569
1570 let mut fruit: fruit::ActiveModel = Default::default();
1571 fruit.set_from_json(json!({
1572 "name": "Apple",
1573 }))?;
1574 fruit.save(&db)?;
1575
1576 let mut fruit = fruit::ActiveModel {
1577 id: Set(2),
1578 ..Default::default()
1579 };
1580 fruit.set_from_json(json!({
1581 "id": 9,
1582 "name": "Orange",
1583 "cake_id": 1,
1584 }))?;
1585 fruit.save(&db)?;
1586
1587 assert_eq!(
1588 db.into_transaction_log(),
1589 [
1590 Transaction::from_sql_and_values(
1591 DbBackend::Postgres,
1592 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1593 ["Apple".into()],
1594 ),
1595 Transaction::from_sql_and_values(
1596 DbBackend::Postgres,
1597 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1598 ["Orange".into(), 1i32.into(), 2i32.into()],
1599 ),
1600 ]
1601 );
1602
1603 Ok(())
1604 }
1605
1606 #[test]
1607 fn test_active_model_is_changed() {
1608 let mut fruit: fruit::ActiveModel = Default::default();
1609 assert!(!fruit.is_changed());
1610
1611 fruit.set(fruit::Column::Name, "apple".into());
1612 assert!(fruit.is_changed());
1613
1614 let mut fruit = fruit::Model {
1615 id: 1,
1616 name: "".into(),
1617 cake_id: None,
1618 };
1619 fruit.set("name".parse().unwrap(), "orange".into());
1620 assert_eq!(fruit.name, "orange");
1621 }
1622
1623 #[test]
1624 fn test_reset_1() {
1625 assert_eq!(
1626 fruit::Model {
1627 id: 1,
1628 name: "Apple".into(),
1629 cake_id: None,
1630 }
1631 .into_active_model(),
1632 fruit::ActiveModel {
1633 id: Unchanged(1),
1634 name: Unchanged("Apple".into()),
1635 cake_id: Unchanged(None)
1636 },
1637 );
1638
1639 assert_eq!(
1640 fruit::Model {
1641 id: 1,
1642 name: "Apple".into(),
1643 cake_id: None,
1644 }
1645 .into_active_model()
1646 .reset_all(),
1647 fruit::ActiveModel {
1648 id: Set(1),
1649 name: Set("Apple".into()),
1650 cake_id: Set(None)
1651 },
1652 );
1653
1654 assert_eq!(
1655 fruit::Model {
1656 id: 1,
1657 name: "Apple".into(),
1658 cake_id: Some(2),
1659 }
1660 .into_active_model(),
1661 fruit::ActiveModel {
1662 id: Unchanged(1),
1663 name: Unchanged("Apple".into()),
1664 cake_id: Unchanged(Some(2)),
1665 },
1666 );
1667
1668 assert_eq!(
1669 fruit::Model {
1670 id: 1,
1671 name: "Apple".into(),
1672 cake_id: Some(2),
1673 }
1674 .into_active_model()
1675 .reset_all(),
1676 fruit::ActiveModel {
1677 id: Set(1),
1678 name: Set("Apple".into()),
1679 cake_id: Set(Some(2)),
1680 },
1681 );
1682 }
1683
1684 #[test]
1685 fn test_reset_2() -> Result<(), DbErr> {
1686 use crate::*;
1687
1688 let db = MockDatabase::new(DbBackend::Postgres)
1689 .append_exec_results(vec![
1690 MockExecResult {
1691 last_insert_id: 1,
1692 rows_affected: 1,
1693 },
1694 MockExecResult {
1695 last_insert_id: 1,
1696 rows_affected: 1,
1697 },
1698 ])
1699 .append_query_results(vec![
1700 vec![fruit::Model {
1701 id: 1,
1702 name: "Apple".to_owned(),
1703 cake_id: None,
1704 }],
1705 vec![fruit::Model {
1706 id: 1,
1707 name: "Apple".to_owned(),
1708 cake_id: None,
1709 }],
1710 ])
1711 .into_connection();
1712
1713 fruit::Model {
1714 id: 1,
1715 name: "Apple".into(),
1716 cake_id: None,
1717 }
1718 .into_active_model()
1719 .update(&db)?;
1720
1721 fruit::Model {
1722 id: 1,
1723 name: "Apple".into(),
1724 cake_id: None,
1725 }
1726 .into_active_model()
1727 .reset_all()
1728 .update(&db)?;
1729
1730 assert_eq!(
1731 db.into_transaction_log(),
1732 vec![
1733 Transaction::from_sql_and_values(
1734 DbBackend::Postgres,
1735 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1736 vec![1i32.into(), 1u64.into()],
1737 ),
1738 Transaction::from_sql_and_values(
1739 DbBackend::Postgres,
1740 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1741 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1742 ),
1743 ]
1744 );
1745
1746 Ok(())
1747 }
1748
1749 #[test]
1750 fn test_active_model_default_values() {
1751 assert_eq!(
1752 fruit::ActiveModel::default_values(),
1753 fruit::ActiveModel {
1754 id: Set(0),
1755 name: Set("".into()),
1756 cake_id: Set(None),
1757 },
1758 );
1759
1760 assert_eq!(
1761 lunch_set::ActiveModel::default_values(),
1762 lunch_set::ActiveModel {
1763 id: Set(0),
1764 name: Set("".into()),
1765 tea: NotSet,
1766 },
1767 );
1768 }
1769
1770 #[test]
1771 fn test_active_model_set_parent_key() {
1772 let mut fruit = fruit::Model {
1773 id: 2,
1774 name: "F".into(),
1775 cake_id: None,
1776 }
1777 .into_active_model();
1778
1779 let cake = cake::Model {
1780 id: 4,
1781 name: "C".into(),
1782 }
1783 .into_active_model();
1784
1785 fruit.set_parent_key(&cake).unwrap();
1786
1787 assert_eq!(
1788 fruit,
1789 fruit::ActiveModel {
1790 id: Unchanged(2),
1791 name: Unchanged("F".into()),
1792 cake_id: Set(Some(4)),
1793 }
1794 );
1795
1796 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1797
1798 assert_eq!(
1799 fruit,
1800 fruit::ActiveModel {
1801 id: Unchanged(2),
1802 name: Unchanged("F".into()),
1803 cake_id: Set(None),
1804 }
1805 );
1806
1807 let mut cake_filling = cake_filling::ActiveModel::new();
1808
1809 cake_filling.set_parent_key(&cake).unwrap();
1810
1811 assert_eq!(
1812 cake_filling,
1813 cake_filling::ActiveModel {
1814 cake_id: Set(4),
1815 filling_id: NotSet,
1816 }
1817 );
1818 }
1819}