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)]
754 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
755 where
756 AM: ActiveModelTrait,
757 Self::Entity: Related<AM::Entity>,
758 {
759 self.find_related(AM::Entity::default())
760 }
761
762 #[doc(hidden)]
765 fn establish_links<J, R, RM, C>(
766 &self,
767 _: J,
768 related_models: &[RM],
769 delete_leftover: bool,
770 db: &C,
771 ) -> Result<(), DbErr>
772 where
773 R: EntityTrait,
774 RM: ActiveModelTrait<Entity = R>,
775 J: EntityTrait + Related<R> + Related<Self::Entity>,
776 J::Model: IntoActiveModel<J::ActiveModel>,
777 J::ActiveModel: ActiveModelBehavior,
778 C: ConnectionTrait,
779 {
780 let left = <J as Related<Self::Entity>>::to();
781 let right = <J as Related<R>>::to();
782
783 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
784 }
785
786 #[doc(hidden)]
788 fn establish_links_self<J, RM, C>(
789 &self,
790 _: J,
791 related_models: &[RM],
792 delete_leftover: bool,
793 db: &C,
794 ) -> Result<(), DbErr>
795 where
796 RM: ActiveModelTrait<Entity = Self::Entity>,
797 J: EntityTrait,
798 J::Model: IntoActiveModel<J::ActiveModel>,
799 J::ActiveModel: ActiveModelBehavior,
800 C: ConnectionTrait,
801 Self::Entity: RelatedSelfVia<J>,
802 {
803 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
804 let right = <Self::Entity as RelatedSelfVia<J>>::to();
805
806 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
807 }
808
809 #[doc(hidden)]
811 fn establish_links_self_rev<J, RM, C>(
812 &self,
813 _: J,
814 related_models: &[RM],
815 delete_leftover: bool,
816 db: &C,
817 ) -> Result<(), DbErr>
818 where
819 RM: ActiveModelTrait<Entity = Self::Entity>,
820 J: EntityTrait,
821 J::Model: IntoActiveModel<J::ActiveModel>,
822 J::ActiveModel: ActiveModelBehavior,
823 C: ConnectionTrait,
824 Self::Entity: RelatedSelfVia<J>,
825 {
826 let left = <Self::Entity as RelatedSelfVia<J>>::to();
827 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
828
829 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
830 }
831
832 #[doc(hidden)]
834 fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
835 where
836 J: EntityTrait + Related<Self::Entity>,
837 C: ConnectionTrait,
838 {
839 let rel_def = <J as Related<Self::Entity>>::to();
840 let id = get_key_from_active_model(&rel_def.to_col, self)?;
841
842 J::delete_many()
843 .filter(
844 column_tuple_in_condition(
845 &rel_def.from_tbl,
846 &rel_def.from_col,
847 &[id],
848 DbBackend::Sqlite,
849 )
850 .expect(""),
851 )
852 .exec(db)
853 }
854
855 #[doc(hidden)]
857 fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
858 where
859 J: EntityTrait,
860 C: ConnectionTrait,
861 Self::Entity: RelatedSelfVia<J>,
862 {
863 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
864 let right = <Self::Entity as RelatedSelfVia<J>>::to();
865
866 let id = get_key_from_active_model(&left.to_col, self)?;
867
868 if left.to_col != right.to_col {
869 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
870 }
871
872 J::delete_many()
873 .filter(
874 Condition::any()
875 .add(
876 column_tuple_in_condition(
877 &left.from_tbl,
878 &left.from_col,
879 std::slice::from_ref(&id),
880 DbBackend::Sqlite,
881 )
882 .expect(""),
883 )
884 .add(
885 column_tuple_in_condition(
886 &right.from_tbl,
887 &right.from_col,
888 std::slice::from_ref(&id),
889 DbBackend::Sqlite,
890 )
891 .expect(""),
892 ),
893 )
894 .exec(db)
895 }
896}
897
898#[allow(unused_variables)]
926pub trait ActiveModelBehavior: ActiveModelTrait {
927 fn new() -> Self {
940 <Self as ActiveModelTrait>::default()
941 }
942
943 fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
945 where
946 C: ConnectionTrait,
947 {
948 Ok(self)
949 }
950
951 fn after_save<C>(
953 model: <Self::Entity as EntityTrait>::Model,
954 db: &C,
955 insert: bool,
956 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
957 where
958 C: ConnectionTrait,
959 {
960 Ok(model)
961 }
962
963 fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
965 where
966 C: ConnectionTrait,
967 {
968 Ok(self)
969 }
970
971 fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
973 where
974 C: ConnectionTrait,
975 {
976 Ok(self)
977 }
978}
979
980pub trait IntoActiveModel<A>
982where
983 A: ActiveModelTrait,
984{
985 fn into_active_model(self) -> A;
987}
988
989impl<A> IntoActiveModel<A> for A
990where
991 A: ActiveModelTrait,
992{
993 fn into_active_model(self) -> A {
994 self
995 }
996}
997
998fn establish_links<EM, J, RM, C>(
999 model: &EM,
1000 related_models: &[RM],
1001 left: RelationDef,
1002 right: RelationDef,
1003 delete_leftover: bool,
1004 db: &C,
1005) -> Result<(), DbErr>
1006where
1007 EM: ActiveModelTrait,
1008 RM: ActiveModelTrait,
1009 J: EntityTrait,
1010 J::Model: IntoActiveModel<J::ActiveModel>,
1011 J::ActiveModel: ActiveModelBehavior,
1012 C: ConnectionTrait,
1013{
1014 let mut require_leftover = true;
1015
1016 if related_models.is_empty() {
1017 require_leftover = false;
1019 }
1020
1021 let primary_key = J::primary_key_identity();
1022 if require_leftover
1023 && primary_key.fully_contains(&left.from_col)
1024 && primary_key.fully_contains(&right.from_col)
1025 {
1026 require_leftover = false;
1029 }
1030
1031 let mut leftover = Vec::new();
1032 if delete_leftover || require_leftover {
1033 for item in
1034 <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(&left, model)?.all(db)?
1035 {
1036 let item = item.into_active_model();
1037 let key = get_key_from_active_model(&right.from_col, &item)?;
1038 leftover.push((item, key));
1039 }
1040 }
1041 let leftover = leftover; let mut via_models = Vec::new();
1044 let mut all_keys = std::collections::HashSet::new();
1045
1046 for related_model in related_models {
1047 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1048 via.set_parent_key_for_def(model, &left)?;
1049 via.set_parent_key_for_def(related_model, &right)?;
1050 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1051 if !leftover.iter().any(|t| t.1 == via_key) {
1052 via_models.push(via);
1054 }
1055 if delete_leftover {
1056 all_keys.insert(via_key);
1057 }
1058 }
1059
1060 if delete_leftover {
1061 let mut to_delete = Vec::new();
1062 for (leftover, key) in leftover {
1063 if !all_keys.contains(&key) {
1064 to_delete.push(
1065 leftover
1066 .get_primary_key_value()
1067 .expect("item is a full model"),
1068 );
1069 }
1070 }
1071 if !to_delete.is_empty() {
1072 J::delete_many()
1073 .filter_by_value_tuples(&to_delete)
1074 .exec(db)?;
1075 }
1076 }
1077
1078 if !via_models.is_empty() {
1079 J::insert_many(via_models)
1081 .on_conflict_do_nothing()
1082 .exec(db)?;
1083 }
1084
1085 Ok(())
1086}
1087
1088#[cfg(test)]
1089mod tests {
1090 use crate::{DbErr, entity::*, tests_cfg::*};
1091 use pretty_assertions::assert_eq;
1092
1093 #[cfg(feature = "with-json")]
1094 use serde_json::json;
1095
1096 #[test]
1097 #[cfg(feature = "macros")]
1098 fn test_derive_into_active_model_1() {
1099 mod my_fruit {
1100 pub use super::fruit::*;
1101 use crate as sea_orm;
1102 use crate::entity::prelude::*;
1103
1104 #[derive(DeriveIntoActiveModel)]
1105 pub struct NewFruit {
1106 pub name: String,
1108 pub cake_id: i32,
1110 }
1111 }
1112
1113 assert_eq!(
1114 my_fruit::NewFruit {
1115 name: "Apple".to_owned(),
1116 cake_id: 1,
1117 }
1118 .into_active_model(),
1119 fruit::ActiveModel {
1120 id: NotSet,
1121 name: Set("Apple".to_owned()),
1122 cake_id: Set(Some(1)),
1123 }
1124 );
1125 }
1126
1127 #[test]
1128 #[cfg(feature = "macros")]
1129 fn test_derive_into_active_model_2() {
1130 use crate as sea_orm;
1131 use crate::entity::prelude::*;
1132
1133 #[derive(DeriveIntoActiveModel)]
1134 #[sea_orm(active_model = "fruit::ActiveModel")]
1135 struct RequiredFruitName {
1136 name: String,
1137 }
1138
1139 assert_eq!(
1140 RequiredFruitName {
1141 name: "Apple Pie".to_owned(),
1142 }
1143 .into_active_model(),
1144 fruit::ActiveModel {
1145 id: NotSet,
1146 name: Set("Apple Pie".to_owned()),
1147 cake_id: NotSet,
1148 }
1149 );
1150
1151 #[derive(DeriveIntoActiveModel)]
1152 #[sea_orm(active_model = "fruit::ActiveModel")]
1153 struct OptionalFruitName {
1154 name: Option<String>,
1155 }
1156
1157 assert_eq!(
1158 OptionalFruitName {
1159 name: Some("Apple Pie".to_owned()),
1160 }
1161 .into_active_model(),
1162 fruit::ActiveModel {
1163 id: NotSet,
1164 name: Set("Apple Pie".to_owned()),
1165 cake_id: NotSet,
1166 }
1167 );
1168
1169 assert_eq!(
1170 OptionalFruitName { name: None }.into_active_model(),
1171 fruit::ActiveModel {
1172 id: NotSet,
1173 name: NotSet,
1174 cake_id: NotSet,
1175 }
1176 );
1177
1178 #[derive(DeriveIntoActiveModel)]
1179 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1180 struct RequiredAndNotNullFruitCake {
1181 cake_id: i32,
1182 }
1183
1184 assert_eq!(
1185 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1186 fruit::ActiveModel {
1187 id: NotSet,
1188 name: NotSet,
1189 cake_id: Set(Some(1)),
1190 }
1191 );
1192
1193 #[derive(DeriveIntoActiveModel)]
1194 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1195 struct OptionalAndNotNullFruitCake {
1196 cake_id: Option<i32>,
1197 }
1198
1199 assert_eq!(
1200 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1201 fruit::ActiveModel {
1202 id: NotSet,
1203 name: NotSet,
1204 cake_id: Set(Some(1)),
1205 }
1206 );
1207
1208 assert_eq!(
1209 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1210 fruit::ActiveModel {
1211 id: NotSet,
1212 name: NotSet,
1213 cake_id: NotSet,
1214 }
1215 );
1216
1217 #[derive(DeriveIntoActiveModel)]
1218 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1219 struct OptionalAndNullableFruitCake {
1220 cake_id: Option<Option<i32>>,
1221 }
1222
1223 assert_eq!(
1224 OptionalAndNullableFruitCake {
1225 cake_id: Some(Some(1)),
1226 }
1227 .into_active_model(),
1228 fruit::ActiveModel {
1229 id: NotSet,
1230 name: NotSet,
1231 cake_id: Set(Some(1)),
1232 }
1233 );
1234
1235 assert_eq!(
1236 OptionalAndNullableFruitCake {
1237 cake_id: Some(None),
1238 }
1239 .into_active_model(),
1240 fruit::ActiveModel {
1241 id: NotSet,
1242 name: NotSet,
1243 cake_id: Set(None),
1244 }
1245 );
1246
1247 assert_eq!(
1248 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1249 fruit::ActiveModel {
1250 id: NotSet,
1251 name: NotSet,
1252 cake_id: NotSet,
1253 }
1254 );
1255 }
1256
1257 #[test]
1258 #[cfg(feature = "macros")]
1259 fn test_derive_try_into_model_1() {
1260 mod my_fruit {
1261 use crate as sea_orm;
1262 use crate::entity::prelude::*;
1263
1264 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1265 #[sea_orm(table_name = "fruit")]
1266 pub struct Model {
1267 #[sea_orm(primary_key)]
1268 pub id: i32,
1269 pub name: String,
1270 pub cake_id: Option<i32>,
1271 }
1272
1273 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1274 pub enum Relation {}
1275
1276 impl ActiveModelBehavior for ActiveModel {}
1277 }
1278 assert_eq!(
1279 my_fruit::ActiveModel {
1280 id: Set(1),
1281 name: Set("Pineapple".to_owned()),
1282 cake_id: Set(None),
1283 }
1284 .try_into_model()
1285 .unwrap(),
1286 my_fruit::Model {
1287 id: 1,
1288 name: "Pineapple".to_owned(),
1289 cake_id: None,
1290 }
1291 );
1292
1293 assert_eq!(
1294 my_fruit::ActiveModel {
1295 id: Set(2),
1296 name: Set("Apple".to_owned()),
1297 cake_id: Set(Some(1)),
1298 }
1299 .try_into_model()
1300 .unwrap(),
1301 my_fruit::Model {
1302 id: 2,
1303 name: "Apple".to_owned(),
1304 cake_id: Some(1),
1305 }
1306 );
1307
1308 assert_eq!(
1309 my_fruit::ActiveModel {
1310 id: Set(1),
1311 name: NotSet,
1312 cake_id: Set(None),
1313 }
1314 .try_into_model(),
1315 Err(DbErr::AttrNotSet(String::from("name")))
1316 );
1317
1318 assert_eq!(
1319 my_fruit::ActiveModel {
1320 id: Set(1),
1321 name: Set("Pineapple".to_owned()),
1322 cake_id: NotSet,
1323 }
1324 .try_into_model(),
1325 Err(DbErr::AttrNotSet(String::from("cake_id")))
1326 );
1327 }
1328
1329 #[test]
1330 #[cfg(feature = "macros")]
1331 fn test_derive_try_into_model_2() {
1332 mod my_fruit {
1333 use crate as sea_orm;
1334 use crate::entity::prelude::*;
1335
1336 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1337 #[sea_orm(table_name = "fruit")]
1338 pub struct Model {
1339 #[sea_orm(primary_key)]
1340 pub id: i32,
1341 pub name: String,
1342 #[sea_orm(ignore)]
1343 pub cake_id: Option<i32>,
1344 }
1345
1346 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1347 pub enum Relation {}
1348
1349 impl ActiveModelBehavior for ActiveModel {}
1350 }
1351 assert_eq!(
1352 my_fruit::ActiveModel {
1353 id: Set(1),
1354 name: Set("Pineapple".to_owned()),
1355 }
1356 .try_into_model()
1357 .unwrap(),
1358 my_fruit::Model {
1359 id: 1,
1360 name: "Pineapple".to_owned(),
1361 cake_id: None,
1362 }
1363 );
1364 }
1365
1366 #[test]
1367 #[cfg(feature = "macros")]
1368 fn test_derive_try_into_model_3() {
1369 mod my_fruit {
1370 use crate as sea_orm;
1371 use crate::entity::prelude::*;
1372
1373 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1374 #[sea_orm(table_name = "fruit")]
1375 pub struct Model {
1376 #[sea_orm(primary_key)]
1377 pub id: i32,
1378 #[sea_orm(ignore)]
1379 pub name: String,
1380 pub cake_id: Option<i32>,
1381 }
1382
1383 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1384 pub enum Relation {}
1385
1386 impl ActiveModelBehavior for ActiveModel {}
1387 }
1388 assert_eq!(
1389 my_fruit::ActiveModel {
1390 id: Set(1),
1391 cake_id: Set(Some(1)),
1392 }
1393 .try_into_model()
1394 .unwrap(),
1395 my_fruit::Model {
1396 id: 1,
1397 name: "".to_owned(),
1398 cake_id: Some(1),
1399 }
1400 );
1401 }
1402
1403 #[test]
1404 #[cfg(feature = "with-json")]
1405 fn test_active_model_set_from_json_1() {
1406 assert_eq!(
1407 cake::ActiveModel::from_json(json!({
1408 "id": 1,
1409 "name": "Apple Pie",
1410 }))
1411 .unwrap(),
1412 cake::ActiveModel {
1413 id: Set(1),
1414 name: Set("Apple Pie".to_owned()),
1415 }
1416 );
1417
1418 assert_eq!(
1419 cake::ActiveModel::from_json(json!({
1420 "id": 1,
1421 }))
1422 .unwrap(),
1423 cake::ActiveModel {
1424 id: Set(1),
1425 name: NotSet,
1426 }
1427 );
1428
1429 assert_eq!(
1430 cake::ActiveModel::from_json(json!({
1431 "name": "Apple Pie",
1432 }))
1433 .unwrap(),
1434 cake::ActiveModel {
1435 id: NotSet,
1436 name: Set("Apple Pie".to_owned()),
1437 }
1438 );
1439
1440 let mut cake: cake::ActiveModel = Default::default();
1441 cake.set_from_json(json!({
1442 "name": "Apple Pie",
1443 }))
1444 .unwrap();
1445 assert_eq!(
1446 cake,
1447 cake::ActiveModel {
1448 id: NotSet,
1449 name: Set("Apple Pie".to_owned()),
1450 }
1451 );
1452 }
1453
1454 #[test]
1455 #[cfg(feature = "with-json")]
1456 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1457 let mut fruit: fruit::ActiveModel = Default::default();
1458
1459 fruit.set_from_json(json!({
1460 "name": "Apple",
1461 }))?;
1462 assert_eq!(
1463 fruit,
1464 fruit::ActiveModel {
1465 id: ActiveValue::NotSet,
1466 name: ActiveValue::Set("Apple".to_owned()),
1467 cake_id: ActiveValue::NotSet,
1468 }
1469 );
1470
1471 assert_eq!(
1472 fruit::ActiveModel::from_json(json!({
1473 "name": "Apple",
1474 }))?,
1475 fruit::ActiveModel {
1476 id: ActiveValue::NotSet,
1477 name: ActiveValue::Set("Apple".to_owned()),
1478 cake_id: ActiveValue::NotSet,
1479 }
1480 );
1481
1482 fruit.set_from_json(json!({
1483 "name": "Apple",
1484 "cake_id": null,
1485 }))?;
1486 assert_eq!(
1487 fruit,
1488 fruit::ActiveModel {
1489 id: ActiveValue::NotSet,
1490 name: ActiveValue::Set("Apple".to_owned()),
1491 cake_id: ActiveValue::Set(None),
1492 }
1493 );
1494
1495 fruit.set_from_json(json!({
1496 "id": null,
1497 "name": "Apple",
1498 "cake_id": 1,
1499 }))?;
1500 assert_eq!(
1501 fruit,
1502 fruit::ActiveModel {
1503 id: ActiveValue::NotSet,
1504 name: ActiveValue::Set("Apple".to_owned()),
1505 cake_id: ActiveValue::Set(Some(1)),
1506 }
1507 );
1508
1509 fruit.set_from_json(json!({
1510 "id": 2,
1511 "name": "Apple",
1512 "cake_id": 1,
1513 }))?;
1514 assert_eq!(
1515 fruit,
1516 fruit::ActiveModel {
1517 id: ActiveValue::NotSet,
1518 name: ActiveValue::Set("Apple".to_owned()),
1519 cake_id: ActiveValue::Set(Some(1)),
1520 }
1521 );
1522
1523 let mut fruit = fruit::ActiveModel {
1524 id: ActiveValue::Set(1),
1525 name: ActiveValue::NotSet,
1526 cake_id: ActiveValue::NotSet,
1527 };
1528 fruit.set_from_json(json!({
1529 "id": 8,
1530 "name": "Apple",
1531 "cake_id": 1,
1532 }))?;
1533 assert_eq!(
1534 fruit,
1535 fruit::ActiveModel {
1536 id: ActiveValue::Set(1),
1537 name: ActiveValue::Set("Apple".to_owned()),
1538 cake_id: ActiveValue::Set(Some(1)),
1539 }
1540 );
1541
1542 Ok(())
1543 }
1544
1545 #[test]
1546 #[cfg(feature = "with-json")]
1547 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1548 use crate::*;
1549
1550 let db = MockDatabase::new(DbBackend::Postgres)
1551 .append_exec_results([
1552 MockExecResult {
1553 last_insert_id: 1,
1554 rows_affected: 1,
1555 },
1556 MockExecResult {
1557 last_insert_id: 1,
1558 rows_affected: 1,
1559 },
1560 ])
1561 .append_query_results([
1562 [fruit::Model {
1563 id: 1,
1564 name: "Apple".to_owned(),
1565 cake_id: None,
1566 }],
1567 [fruit::Model {
1568 id: 2,
1569 name: "Orange".to_owned(),
1570 cake_id: Some(1),
1571 }],
1572 ])
1573 .into_connection();
1574
1575 let mut fruit: fruit::ActiveModel = Default::default();
1576 fruit.set_from_json(json!({
1577 "name": "Apple",
1578 }))?;
1579 fruit.save(&db)?;
1580
1581 let mut fruit = fruit::ActiveModel {
1582 id: Set(2),
1583 ..Default::default()
1584 };
1585 fruit.set_from_json(json!({
1586 "id": 9,
1587 "name": "Orange",
1588 "cake_id": 1,
1589 }))?;
1590 fruit.save(&db)?;
1591
1592 assert_eq!(
1593 db.into_transaction_log(),
1594 [
1595 Transaction::from_sql_and_values(
1596 DbBackend::Postgres,
1597 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1598 ["Apple".into()],
1599 ),
1600 Transaction::from_sql_and_values(
1601 DbBackend::Postgres,
1602 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1603 ["Orange".into(), 1i32.into(), 2i32.into()],
1604 ),
1605 ]
1606 );
1607
1608 Ok(())
1609 }
1610
1611 #[test]
1612 fn test_active_model_is_changed() {
1613 let mut fruit: fruit::ActiveModel = Default::default();
1614 assert!(!fruit.is_changed());
1615
1616 fruit.set(fruit::Column::Name, "apple".into());
1617 assert!(fruit.is_changed());
1618
1619 let mut fruit = fruit::Model {
1620 id: 1,
1621 name: "".into(),
1622 cake_id: None,
1623 };
1624 fruit.set("name".parse().unwrap(), "orange".into());
1625 assert_eq!(fruit.name, "orange");
1626 }
1627
1628 #[test]
1629 fn test_reset_1() {
1630 assert_eq!(
1631 fruit::Model {
1632 id: 1,
1633 name: "Apple".into(),
1634 cake_id: None,
1635 }
1636 .into_active_model(),
1637 fruit::ActiveModel {
1638 id: Unchanged(1),
1639 name: Unchanged("Apple".into()),
1640 cake_id: Unchanged(None)
1641 },
1642 );
1643
1644 assert_eq!(
1645 fruit::Model {
1646 id: 1,
1647 name: "Apple".into(),
1648 cake_id: None,
1649 }
1650 .into_active_model()
1651 .reset_all(),
1652 fruit::ActiveModel {
1653 id: Set(1),
1654 name: Set("Apple".into()),
1655 cake_id: Set(None)
1656 },
1657 );
1658
1659 assert_eq!(
1660 fruit::Model {
1661 id: 1,
1662 name: "Apple".into(),
1663 cake_id: Some(2),
1664 }
1665 .into_active_model(),
1666 fruit::ActiveModel {
1667 id: Unchanged(1),
1668 name: Unchanged("Apple".into()),
1669 cake_id: Unchanged(Some(2)),
1670 },
1671 );
1672
1673 assert_eq!(
1674 fruit::Model {
1675 id: 1,
1676 name: "Apple".into(),
1677 cake_id: Some(2),
1678 }
1679 .into_active_model()
1680 .reset_all(),
1681 fruit::ActiveModel {
1682 id: Set(1),
1683 name: Set("Apple".into()),
1684 cake_id: Set(Some(2)),
1685 },
1686 );
1687 }
1688
1689 #[test]
1690 fn test_reset_2() -> Result<(), DbErr> {
1691 use crate::*;
1692
1693 let db = MockDatabase::new(DbBackend::Postgres)
1694 .append_exec_results(vec![
1695 MockExecResult {
1696 last_insert_id: 1,
1697 rows_affected: 1,
1698 },
1699 MockExecResult {
1700 last_insert_id: 1,
1701 rows_affected: 1,
1702 },
1703 ])
1704 .append_query_results(vec![
1705 vec![fruit::Model {
1706 id: 1,
1707 name: "Apple".to_owned(),
1708 cake_id: None,
1709 }],
1710 vec![fruit::Model {
1711 id: 1,
1712 name: "Apple".to_owned(),
1713 cake_id: None,
1714 }],
1715 ])
1716 .into_connection();
1717
1718 fruit::Model {
1719 id: 1,
1720 name: "Apple".into(),
1721 cake_id: None,
1722 }
1723 .into_active_model()
1724 .update(&db)?;
1725
1726 fruit::Model {
1727 id: 1,
1728 name: "Apple".into(),
1729 cake_id: None,
1730 }
1731 .into_active_model()
1732 .reset_all()
1733 .update(&db)?;
1734
1735 assert_eq!(
1736 db.into_transaction_log(),
1737 vec![
1738 Transaction::from_sql_and_values(
1739 DbBackend::Postgres,
1740 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1741 vec![1i32.into(), 1u64.into()],
1742 ),
1743 Transaction::from_sql_and_values(
1744 DbBackend::Postgres,
1745 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1746 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1747 ),
1748 ]
1749 );
1750
1751 Ok(())
1752 }
1753
1754 #[test]
1755 fn test_active_model_default_values() {
1756 assert_eq!(
1757 fruit::ActiveModel::default_values(),
1758 fruit::ActiveModel {
1759 id: Set(0),
1760 name: Set("".into()),
1761 cake_id: Set(None),
1762 },
1763 );
1764
1765 assert_eq!(
1766 lunch_set::ActiveModel::default_values(),
1767 lunch_set::ActiveModel {
1768 id: Set(0),
1769 name: Set("".into()),
1770 tea: NotSet,
1771 },
1772 );
1773 }
1774
1775 #[test]
1776 fn test_active_model_set_parent_key() {
1777 let mut fruit = fruit::Model {
1778 id: 2,
1779 name: "F".into(),
1780 cake_id: None,
1781 }
1782 .into_active_model();
1783
1784 let cake = cake::Model {
1785 id: 4,
1786 name: "C".into(),
1787 }
1788 .into_active_model();
1789
1790 fruit.set_parent_key(&cake).unwrap();
1791
1792 assert_eq!(
1793 fruit,
1794 fruit::ActiveModel {
1795 id: Unchanged(2),
1796 name: Unchanged("F".into()),
1797 cake_id: Set(Some(4)),
1798 }
1799 );
1800
1801 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1802
1803 assert_eq!(
1804 fruit,
1805 fruit::ActiveModel {
1806 id: Unchanged(2),
1807 name: Unchanged("F".into()),
1808 cake_id: Set(None),
1809 }
1810 );
1811
1812 let mut cake_filling = cake_filling::ActiveModel::new();
1813
1814 cake_filling.set_parent_key(&cake).unwrap();
1815
1816 assert_eq!(
1817 cake_filling,
1818 cake_filling::ActiveModel {
1819 cake_id: Set(4),
1820 filling_id: NotSet,
1821 }
1822 );
1823 }
1824}