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, TryInsertResult, UpdateResult, 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 {
31 type Entity: EntityTrait;
33
34 fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
36
37 fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
39
40 fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
43 self.try_set(c, v)
44 .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
45 }
46
47 fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
50
51 fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
53
54 fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
57
58 fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
60
61 fn default() -> Self;
63
64 fn default_values() -> Self;
67
68 fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
72
73 fn reset_all(mut self) -> Self {
76 for col in <Self::Entity as EntityTrait>::Column::iter() {
77 self.reset(col);
78 }
79 self
80 }
81
82 fn get_primary_key_value(&self) -> Option<ValueTuple> {
85 let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
86 macro_rules! next {
87 () => {
88 self.get(cols.next()?.into_column()).into_value()?
89 };
90 }
91 match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
92 1 => {
93 let s1 = next!();
94 Some(ValueTuple::One(s1))
95 }
96 2 => {
97 let s1 = next!();
98 let s2 = next!();
99 Some(ValueTuple::Two(s1, s2))
100 }
101 3 => {
102 let s1 = next!();
103 let s2 = next!();
104 let s3 = next!();
105 Some(ValueTuple::Three(s1, s2, s3))
106 }
107 len => {
108 let mut vec = Vec::with_capacity(len);
109 for _ in 0..len {
110 let s = next!();
111 vec.push(s);
112 }
113 Some(ValueTuple::Many(vec))
114 }
115 }
116 }
117
118 fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
223 where
224 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
225 Self: ActiveModelBehavior,
226 C: ConnectionTrait,
227 {
228 let am = ActiveModelBehavior::before_save(self, db, true)?;
229 let model = <Self::Entity as EntityTrait>::insert(am).exec_with_returning(db)?;
230 Self::after_save(model, db, true)
231 }
232
233 fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
341 where
342 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
343 Self: ActiveModelBehavior,
344 C: ConnectionTrait,
345 {
346 let am = ActiveModelBehavior::before_save(self, db, false)?;
347 let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db)?;
348 Self::after_save(model, db, false)
349 }
350
351 fn update_without_returning<'a, C>(self, db: &'a C) -> Result<UpdateResult, DbErr>
360 where
361 Self: ActiveModelBehavior,
362 C: ConnectionTrait,
363 {
364 let am = ActiveModelBehavior::before_save(self, db, false)?;
365 Self::Entity::update(am).exec_without_returning(db)
366 }
367
368 fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
371 where
372 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
373 Self: ActiveModelBehavior,
374 C: ConnectionTrait,
375 {
376 let res = if !self.is_update() {
377 self.insert(db)
378 } else {
379 self.update(db)
380 }?;
381 Ok(res.into_active_model())
382 }
383
384 #[doc(hidden)]
386 fn is_update(&self) -> bool {
387 let mut is_update = true;
388 for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
389 let col = key.into_column();
390 if self.is_not_set(col) {
391 is_update = false;
392 break;
393 }
394 }
395 is_update
396 }
397
398 fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
441 where
442 Self: ActiveModelBehavior,
443 C: ConnectionTrait,
444 {
445 let am = ActiveModelBehavior::before_delete(self, db)?;
446 let am_clone = am.clone();
447 let delete_res = Self::Entity::delete(am).exec(db)?;
448 ActiveModelBehavior::after_delete(am_clone, db)?;
449 Ok(delete_res)
450 }
451
452 #[cfg(feature = "with-json")]
456 fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
457 where
458 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
459 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
460 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
461 serde::de::Deserialize<'de> + serde::Serialize,
462 {
463 use crate::Iterable;
464
465 let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
467 <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
468 .map(|pk| (pk.into_column(), self.take(pk.into_column())))
469 .collect();
470
471 *self = Self::from_json(json)?;
473
474 for (col, active_value) in primary_key_values {
476 match active_value {
477 ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
478 NotSet => self.not_set(col),
479 }
480 }
481
482 Ok(())
483 }
484
485 #[cfg(feature = "with-json")]
487 fn from_json(json: serde_json::Value) -> Result<Self, DbErr>
488 where
489 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
490 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
491 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
492 serde::de::Deserialize<'de> + serde::Serialize,
493 {
494 use crate::{IdenStatic, Iterable};
495
496 let serde_json::Value::Object(mut input) = json else {
497 return Err(DbErr::Json(format!(
498 "invalid type: expected JSON object for {}",
499 <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
500 )));
501 };
502
503 let dummy_am = Self::default_values();
504 let len = <<Self::Entity as EntityTrait>::Column>::iter().len();
505 let mut json_keys = Vec::with_capacity(len);
507 let mut merged = serde_json::Map::with_capacity(len);
508
509 for col in <<Self::Entity as EntityTrait>::Column>::iter() {
510 let key = col.json_key();
511 let has_key = input.contains_key(key);
512 json_keys.push((col, has_key));
513 match dummy_am.get(col) {
514 ActiveValue::Unchanged(value) | ActiveValue::Set(value) => {
515 merged.insert(key.to_owned(), sea_query::sea_value_to_json_value(&value));
516 }
517 _ => {}
518 }
519 }
520
521 merged.append(&mut input);
522 let _ = input;
523
524 let json_value = serde_json::Value::Object(merged);
525
526 let model: <Self::Entity as EntityTrait>::Model =
528 serde_json::from_value(json_value).map_err(json_err)?;
529 let mut am = model.into_active_model();
530
531 for (col, json_key_exists) in json_keys {
533 match (json_key_exists, am.get(col)) {
534 (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
535 am.set(col, value);
536 }
537 _ => {
538 am.not_set(col);
539 }
540 }
541 }
542
543 Ok(am)
544 }
545
546 #[cfg(feature = "with-arrow")]
561 fn from_arrow(batch: &sea_orm_arrow::arrow::array::RecordBatch) -> Result<Vec<Self>, DbErr> {
562 use crate::{IdenStatic, Iterable, with_arrow::arrow_array_to_value};
563
564 let num_rows = batch.num_rows();
565 let mut results = Vec::with_capacity(num_rows);
566
567 for row in 0..num_rows {
568 let mut am = Self::default();
569
570 for col in <<Self::Entity as EntityTrait>::Column>::iter() {
571 let col_name = col.as_str();
572
573 if let Some(arrow_col) = batch.column_by_name(col_name) {
574 let col_def = col.def();
575 let col_type = col_def.get_column_type();
576 let value = arrow_array_to_value(arrow_col.as_ref(), col_type, row)?;
577
578 #[cfg(all(feature = "with-chrono", feature = "with-time"))]
583 {
584 use crate::with_arrow::{arrow_array_to_value_alt, is_datetime_column};
585 match am.try_set(col, value) {
586 Ok(()) => {}
587 Err(first_err) if is_datetime_column(col_type) => {
588 if let Some(alt_value) =
589 arrow_array_to_value_alt(arrow_col.as_ref(), col_type, row)?
590 {
591 am.try_set(col, alt_value)?;
592 } else {
593 return Err(first_err);
594 }
595 }
596 Err(e) => return Err(e),
597 }
598 }
599
600 #[cfg(not(all(feature = "with-chrono", feature = "with-time")))]
601 am.try_set(col, value)?;
602 } else {
603 am.not_set(col);
604 }
605 }
606
607 results.push(am);
608 }
609
610 Ok(results)
611 }
612
613 #[cfg(feature = "with-arrow")]
626 fn to_arrow(
627 models: &[Self],
628 schema: &sea_orm_arrow::arrow::datatypes::Schema,
629 ) -> Result<sea_orm_arrow::arrow::array::RecordBatch, DbErr> {
630 use crate::{Iterable, with_arrow::option_values_to_arrow_array};
631 use std::sync::Arc;
632
633 let mut columns: Vec<Arc<dyn sea_orm_arrow::arrow::array::Array>> =
634 Vec::with_capacity(schema.fields().len());
635
636 for field in schema.fields() {
637 let field_name = field.name();
638
639 let entity_col =
641 <<Self::Entity as EntityTrait>::Column>::iter().find(|c| c.as_str() == field_name);
642
643 if let Some(col) = entity_col {
644 let values: Vec<Option<Value>> = models
645 .iter()
646 .map(|m| match m.get(col) {
647 ActiveValue::Set(v) | ActiveValue::Unchanged(v) => Some(v),
648 ActiveValue::NotSet => None,
649 })
650 .collect();
651
652 let array = option_values_to_arrow_array(&values, field.data_type())?;
653 columns.push(array);
654 } else {
655 let array =
657 sea_orm_arrow::arrow::array::new_null_array(field.data_type(), models.len());
658 columns.push(array);
659 }
660 }
661
662 sea_orm_arrow::arrow::array::RecordBatch::try_new(Arc::new(schema.clone()), columns)
663 .map_err(|e| DbErr::Type(format!("Failed to create RecordBatch: {e}")))
664 }
665
666 fn is_changed(&self) -> bool {
668 <Self::Entity as EntityTrait>::Column::iter()
669 .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
670 }
671
672 #[doc(hidden)]
673 fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
675 where
676 R: EntityTrait,
677 AM: ActiveModelTrait<Entity = R>,
678 Self::Entity: Related<R>,
679 {
680 let rel_def = Self::Entity::to();
681
682 if rel_def.is_owner {
683 return Err(DbErr::Type(format!(
684 "Relation from {} to {} is not belongs_to",
685 <Self::Entity as Default>::default().as_str(),
686 <R as Default>::default().as_str()
687 )));
688 }
689
690 let values = get_key_from_active_model(&rel_def.to_col, model)?;
691
692 set_key_on_active_model(&rel_def.from_col, self, values)?;
693
694 Ok(())
695 }
696
697 #[doc(hidden)]
698 fn set_parent_key_for<R, AM>(
699 &mut self,
700 model: &AM,
701 rel: <Self::Entity as EntityTrait>::Relation,
702 ) -> Result<(), DbErr>
703 where
704 R: EntityTrait,
705 AM: ActiveModelTrait<Entity = R>,
706 {
707 let rel_def = rel.def();
708
709 if rel_def.is_owner {
710 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
711 }
712
713 let values = get_key_from_active_model(&rel_def.to_col, model)?;
714
715 set_key_on_active_model(&rel_def.from_col, self, values)?;
716
717 Ok(())
718 }
719
720 #[doc(hidden)]
721 fn set_parent_key_for_def<R, AM>(
722 &mut self,
723 model: &AM,
724 rel_def: &RelationDef,
725 ) -> Result<(), DbErr>
726 where
727 R: EntityTrait,
728 AM: ActiveModelTrait<Entity = R>,
729 {
730 if rel_def.is_owner {
731 return Err(DbErr::Type(format!(
732 "Relation {rel_def:?} is not belongs_to"
733 )));
734 }
735
736 let values = get_key_from_active_model(&rel_def.to_col, model)?;
737
738 set_key_on_active_model(&rel_def.from_col, self, values)?;
739
740 Ok(())
741 }
742
743 #[doc(hidden)]
744 fn set_parent_key_for_self_rev<AM>(
745 &mut self,
746 model: &AM,
747 rel: <Self::Entity as EntityTrait>::Relation,
748 ) -> Result<(), DbErr>
749 where
750 AM: ActiveModelTrait<Entity = Self::Entity>,
751 {
752 let rel_def = rel.def();
753
754 if !rel_def.is_owner {
755 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
756 }
757
758 let values = get_key_from_active_model(&rel_def.from_col, model)?;
759
760 set_key_on_active_model(&rel_def.to_col, self, values)?;
761
762 Ok(())
763 }
764
765 #[doc(hidden)]
766 fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
768 where
769 R: EntityTrait,
770 Self::Entity: Related<R>,
771 {
772 let rel_def = Self::Entity::to();
773
774 if rel_def.is_owner {
775 return Err(DbErr::Type(format!(
776 "Relation from {} to {} is not belongs_to",
777 <Self::Entity as Default>::default().as_str(),
778 <R as Default>::default().as_str()
779 )));
780 }
781
782 clear_key_on_active_model(&rel_def.from_col, self)
783 }
784
785 #[doc(hidden)]
786 fn clear_parent_key_for_self_rev(
787 &mut self,
788 rel: <Self::Entity as EntityTrait>::Relation,
789 ) -> Result<bool, DbErr> {
790 let rel_def = rel.def();
791
792 if !rel_def.is_owner {
793 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
794 }
795
796 clear_key_on_active_model(&rel_def.to_col, self)
797 }
798
799 #[doc(hidden)]
800 fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
802 where
803 R: EntityTrait,
804 Self::Entity: Related<R>,
805 {
806 let rel_def = Self::Entity::to();
807
808 if rel_def.is_owner {
809 return Err(DbErr::Type(format!(
810 "Relation from {} to {} is not belongs_to",
811 <Self::Entity as Default>::default().as_str(),
812 <R as Default>::default().as_str()
813 )));
814 }
815
816 get_key_from_active_model(&rel_def.from_col, self)
817 }
818
819 #[doc(hidden)]
820 fn get_parent_key_for(
822 &self,
823 rel: <Self::Entity as EntityTrait>::Relation,
824 ) -> Result<ValueTuple, DbErr> {
825 let rel_def = rel.def();
826
827 if rel_def.is_owner {
828 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
829 }
830
831 get_key_from_active_model(&rel_def.from_col, self)
832 }
833
834 #[doc(hidden)]
835 fn find_belongs_to_self(
836 &self,
837 rel: <Self::Entity as EntityTrait>::Relation,
838 db_backend: DbBackend,
839 ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
840 let rel_def = rel.def();
841
842 if !rel_def.is_owner {
843 return Err(DbErr::Type(format!(
844 "Relation {rel:?} is not has_one / has_many"
845 )));
846 }
847
848 let id = get_key_from_active_model(&rel_def.from_col, self)?;
849
850 Ok(Self::Entity::find().filter(
851 column_tuple_in_condition(
852 &<Self::Entity as Default>::default().table_ref(),
853 &rel_def.to_col,
854 &[id],
855 db_backend,
856 )
857 .expect(""),
858 ))
859 }
860
861 #[doc(hidden)]
862 fn find_belongs_to_model<AM>(
863 rel_def: &RelationDef,
864 belongs_to: &AM,
865 db_backend: DbBackend,
866 ) -> Result<crate::query::Select<Self::Entity>, DbErr>
867 where
868 AM: ActiveModelTrait,
869 {
870 if rel_def.is_owner {
871 return Err(DbErr::Type(format!(
872 "Relation {rel_def:?} is not belongs_to"
873 )));
874 }
875
876 let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
877 Ok(<Self::Entity as EntityTrait>::find().filter(
878 column_tuple_in_condition(&rel_def.from_tbl, &rel_def.from_col, &[id], db_backend)
879 .expect(""),
880 ))
881 }
882
883 fn find_related<R>(&self, _: R) -> crate::query::Select<R>
885 where
886 R: EntityTrait,
887 Self::Entity: Related<R>,
888 {
889 Self::Entity::find_related().belongs_to_active_model(self)
890 }
891
892 #[doc(hidden)]
894 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
895 where
896 AM: ActiveModelTrait,
897 Self::Entity: Related<AM::Entity>,
898 {
899 self.find_related(AM::Entity::default())
900 }
901
902 #[doc(hidden)]
905 fn establish_links<J, R, RM, C>(
906 &self,
907 _: J,
908 related_models: &[RM],
909 delete_leftover: bool,
910 db: &C,
911 ) -> Result<(), DbErr>
912 where
913 R: EntityTrait,
914 RM: ActiveModelTrait<Entity = R>,
915 J: EntityTrait + Related<R> + Related<Self::Entity>,
916 J::Model: IntoActiveModel<J::ActiveModel>,
917 J::ActiveModel: ActiveModelBehavior,
918 C: ConnectionTrait,
919 {
920 let left = <J as Related<Self::Entity>>::to();
921 let right = <J as Related<R>>::to();
922
923 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
924 }
925
926 #[doc(hidden)]
928 fn establish_links_self<J, RM, C>(
929 &self,
930 _: J,
931 related_models: &[RM],
932 delete_leftover: bool,
933 db: &C,
934 ) -> Result<(), DbErr>
935 where
936 RM: ActiveModelTrait<Entity = Self::Entity>,
937 J: EntityTrait,
938 J::Model: IntoActiveModel<J::ActiveModel>,
939 J::ActiveModel: ActiveModelBehavior,
940 C: ConnectionTrait,
941 Self::Entity: RelatedSelfVia<J>,
942 {
943 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
944 let right = <Self::Entity as RelatedSelfVia<J>>::to();
945
946 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
947 }
948
949 #[doc(hidden)]
951 fn establish_links_self_rev<J, RM, C>(
952 &self,
953 _: J,
954 related_models: &[RM],
955 delete_leftover: bool,
956 db: &C,
957 ) -> Result<(), DbErr>
958 where
959 RM: ActiveModelTrait<Entity = Self::Entity>,
960 J: EntityTrait,
961 J::Model: IntoActiveModel<J::ActiveModel>,
962 J::ActiveModel: ActiveModelBehavior,
963 C: ConnectionTrait,
964 Self::Entity: RelatedSelfVia<J>,
965 {
966 let left = <Self::Entity as RelatedSelfVia<J>>::to();
967 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
968
969 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
970 }
971
972 #[doc(hidden)]
974 fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
975 where
976 J: EntityTrait + Related<Self::Entity>,
977 C: ConnectionTrait,
978 {
979 let rel_def = <J as Related<Self::Entity>>::to();
980 let id = get_key_from_active_model(&rel_def.to_col, self)?;
981
982 J::delete_many()
983 .filter(
984 column_tuple_in_condition(
985 &rel_def.from_tbl,
986 &rel_def.from_col,
987 &[id],
988 db.get_database_backend(),
989 )
990 .expect(""),
991 )
992 .exec(db)
993 }
994
995 #[doc(hidden)]
997 fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
998 where
999 J: EntityTrait,
1000 C: ConnectionTrait,
1001 Self::Entity: RelatedSelfVia<J>,
1002 {
1003 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
1004 let right = <Self::Entity as RelatedSelfVia<J>>::to();
1005
1006 let id = get_key_from_active_model(&left.to_col, self)?;
1007
1008 if left.to_col != right.to_col {
1009 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
1010 }
1011
1012 J::delete_many()
1013 .filter(
1014 Condition::any()
1015 .add(
1016 column_tuple_in_condition(
1017 &left.from_tbl,
1018 &left.from_col,
1019 std::slice::from_ref(&id),
1020 db.get_database_backend(),
1021 )
1022 .expect(""),
1023 )
1024 .add(
1025 column_tuple_in_condition(
1026 &right.from_tbl,
1027 &right.from_col,
1028 std::slice::from_ref(&id),
1029 db.get_database_backend(),
1030 )
1031 .expect(""),
1032 ),
1033 )
1034 .exec(db)
1035 }
1036}
1037
1038#[allow(unused_variables)]
1064pub trait ActiveModelBehavior: ActiveModelTrait {
1065 fn new() -> Self {
1077 <Self as ActiveModelTrait>::default()
1078 }
1079
1080 fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1083 where
1084 C: ConnectionTrait,
1085 {
1086 Ok(self)
1087 }
1088
1089 fn after_save<C>(
1092 model: <Self::Entity as EntityTrait>::Model,
1093 db: &C,
1094 insert: bool,
1095 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1096 where
1097 C: ConnectionTrait,
1098 {
1099 Ok(model)
1100 }
1101
1102 fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1104 where
1105 C: ConnectionTrait,
1106 {
1107 Ok(self)
1108 }
1109
1110 fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1112 where
1113 C: ConnectionTrait,
1114 {
1115 Ok(self)
1116 }
1117}
1118
1119pub trait IntoActiveModel<A>
1204where
1205 A: ActiveModelTrait,
1206{
1207 fn into_active_model(self) -> A;
1209}
1210
1211impl<A> IntoActiveModel<A> for A
1212where
1213 A: ActiveModelTrait,
1214{
1215 fn into_active_model(self) -> A {
1216 self
1217 }
1218}
1219
1220fn establish_links<EM, J, RM, C>(
1221 model: &EM,
1222 related_models: &[RM],
1223 left: RelationDef,
1224 right: RelationDef,
1225 delete_leftover: bool,
1226 db: &C,
1227) -> Result<(), DbErr>
1228where
1229 EM: ActiveModelTrait,
1230 RM: ActiveModelTrait,
1231 J: EntityTrait,
1232 J::Model: IntoActiveModel<J::ActiveModel>,
1233 J::ActiveModel: ActiveModelBehavior,
1234 C: ConnectionTrait,
1235{
1236 let mut require_leftover = true;
1237
1238 if related_models.is_empty() {
1239 require_leftover = false;
1241 }
1242
1243 let primary_key = J::primary_key_identity();
1244 if require_leftover
1245 && primary_key.fully_contains(&left.from_col)
1246 && primary_key.fully_contains(&right.from_col)
1247 {
1248 require_leftover = false;
1251 }
1252
1253 let mut leftover = Vec::new();
1254 if delete_leftover || require_leftover {
1255 for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1256 &left,
1257 model,
1258 db.get_database_backend(),
1259 )?
1260 .all(db)?
1261 {
1262 let item = item.into_active_model();
1263 let key = get_key_from_active_model(&right.from_col, &item)?;
1264 leftover.push((item, key));
1265 }
1266 }
1267 let leftover = leftover; let mut via_models = Vec::new();
1270 let mut all_keys = std::collections::HashSet::new();
1271
1272 for related_model in related_models {
1273 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1274 via.set_parent_key_for_def(model, &left)?;
1275 via.set_parent_key_for_def(related_model, &right)?;
1276 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1277 if !leftover.iter().any(|t| t.1 == via_key) {
1278 via_models.push(via);
1280 }
1281 if delete_leftover {
1282 all_keys.insert(via_key);
1283 }
1284 }
1285
1286 if delete_leftover {
1287 let mut to_delete = Vec::new();
1288 let mut to_delete_am = Vec::new();
1289 for (leftover, key) in leftover {
1290 if !all_keys.contains(&key) {
1291 to_delete.push(
1292 leftover
1293 .get_primary_key_value()
1294 .expect("item is a full model"),
1295 );
1296 to_delete_am.push(leftover);
1297 }
1298 }
1299 if !to_delete.is_empty() {
1300 for am in to_delete_am.clone() {
1302 am.before_delete(db)?;
1303 }
1304 if db.support_returning() {
1305 let deleted = J::delete_many()
1306 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1307 .exec_with_returning(db)?;
1308 for am in deleted {
1310 let am = am.into_active_model();
1311 let _ = am.after_delete(db)?;
1312 }
1313 } else {
1314 J::delete_many()
1315 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1316 .exec(db)?;
1317 for am in to_delete_am {
1319 let _ = am.after_delete(db)?;
1320 }
1321 }
1322 }
1323 }
1324
1325 if !via_models.is_empty() {
1326 let mut via_models_res = Vec::with_capacity(via_models.len());
1328 for am in via_models {
1329 let am = am.before_save(db, true)?;
1330 via_models_res.push(am);
1331 }
1332
1333 if db.support_returning() {
1335 let res = J::insert_many(via_models_res)
1337 .on_conflict_do_nothing()
1338 .exec_with_returning_many(db)?;
1339 if let TryInsertResult::Inserted(inserted) = res {
1341 for model in inserted {
1342 let _ = J::ActiveModel::after_save(model, db, true)?;
1343 }
1344 }
1345 } else {
1346 for model in via_models_res {
1348 let res = J::insert(model)
1349 .on_conflict_do_nothing()
1350 .exec_with_returning(db)?;
1351 if let TryInsertResult::Inserted(model) = res {
1352 let _ = J::ActiveModel::after_save(model, db, true)?;
1353 }
1354 }
1355 }
1356 }
1357
1358 Ok(())
1359}
1360
1361#[cfg(test)]
1362mod tests {
1363 use crate::{DbErr, entity::*, tests_cfg::*};
1364 use pretty_assertions::assert_eq;
1365
1366 #[cfg(feature = "with-json")]
1367 use serde_json::json;
1368
1369 #[test]
1370 #[cfg(feature = "macros")]
1371 fn test_derive_into_active_model_1() {
1372 mod my_fruit {
1373 pub use super::fruit::*;
1374 use crate as sea_orm;
1375 use crate::entity::prelude::*;
1376
1377 #[derive(DeriveIntoActiveModel)]
1378 pub struct NewFruit {
1379 pub name: String,
1381 pub cake_id: i32,
1383 }
1384 }
1385
1386 assert_eq!(
1387 my_fruit::NewFruit {
1388 name: "Apple".to_owned(),
1389 cake_id: 1,
1390 }
1391 .into_active_model(),
1392 fruit::ActiveModel {
1393 id: NotSet,
1394 name: Set("Apple".to_owned()),
1395 cake_id: Set(Some(1)),
1396 }
1397 );
1398 }
1399
1400 #[test]
1401 #[cfg(feature = "macros")]
1402 fn test_derive_into_active_model_2() {
1403 use crate as sea_orm;
1404 use crate::entity::prelude::*;
1405
1406 #[derive(DeriveIntoActiveModel)]
1407 #[sea_orm(active_model = "fruit::ActiveModel")]
1408 struct RequiredFruitName {
1409 name: String,
1410 }
1411
1412 assert_eq!(
1413 RequiredFruitName {
1414 name: "Apple Pie".to_owned(),
1415 }
1416 .into_active_model(),
1417 fruit::ActiveModel {
1418 id: NotSet,
1419 name: Set("Apple Pie".to_owned()),
1420 cake_id: NotSet,
1421 }
1422 );
1423
1424 #[derive(DeriveIntoActiveModel)]
1425 #[sea_orm(active_model = "fruit::ActiveModel")]
1426 struct OptionalFruitName {
1427 name: Option<String>,
1428 }
1429
1430 assert_eq!(
1431 OptionalFruitName {
1432 name: Some("Apple Pie".to_owned()),
1433 }
1434 .into_active_model(),
1435 fruit::ActiveModel {
1436 id: NotSet,
1437 name: Set("Apple Pie".to_owned()),
1438 cake_id: NotSet,
1439 }
1440 );
1441
1442 assert_eq!(
1443 OptionalFruitName { name: None }.into_active_model(),
1444 fruit::ActiveModel {
1445 id: NotSet,
1446 name: NotSet,
1447 cake_id: NotSet,
1448 }
1449 );
1450
1451 #[derive(DeriveIntoActiveModel)]
1452 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1453 struct RequiredAndNotNullFruitCake {
1454 cake_id: i32,
1455 }
1456
1457 assert_eq!(
1458 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1459 fruit::ActiveModel {
1460 id: NotSet,
1461 name: NotSet,
1462 cake_id: Set(Some(1)),
1463 }
1464 );
1465
1466 #[derive(DeriveIntoActiveModel)]
1467 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1468 struct OptionalAndNotNullFruitCake {
1469 cake_id: Option<i32>,
1470 }
1471
1472 assert_eq!(
1473 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1474 fruit::ActiveModel {
1475 id: NotSet,
1476 name: NotSet,
1477 cake_id: Set(Some(1)),
1478 }
1479 );
1480
1481 assert_eq!(
1482 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1483 fruit::ActiveModel {
1484 id: NotSet,
1485 name: NotSet,
1486 cake_id: NotSet,
1487 }
1488 );
1489
1490 #[derive(DeriveIntoActiveModel)]
1491 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1492 struct OptionalAndNullableFruitCake {
1493 cake_id: Option<Option<i32>>,
1494 }
1495
1496 assert_eq!(
1497 OptionalAndNullableFruitCake {
1498 cake_id: Some(Some(1)),
1499 }
1500 .into_active_model(),
1501 fruit::ActiveModel {
1502 id: NotSet,
1503 name: NotSet,
1504 cake_id: Set(Some(1)),
1505 }
1506 );
1507
1508 assert_eq!(
1509 OptionalAndNullableFruitCake {
1510 cake_id: Some(None),
1511 }
1512 .into_active_model(),
1513 fruit::ActiveModel {
1514 id: NotSet,
1515 name: NotSet,
1516 cake_id: Set(None),
1517 }
1518 );
1519
1520 assert_eq!(
1521 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1522 fruit::ActiveModel {
1523 id: NotSet,
1524 name: NotSet,
1525 cake_id: NotSet,
1526 }
1527 );
1528 }
1529
1530 #[test]
1531 #[cfg(feature = "macros")]
1532 fn test_derive_into_active_model_set_single() {
1533 use crate as sea_orm;
1534 use crate::entity::prelude::*;
1535
1536 #[derive(DeriveIntoActiveModel)]
1537 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1538 struct NewFruit {
1539 name: String,
1540 }
1541
1542 assert_eq!(
1543 NewFruit {
1544 name: "Apple".to_owned(),
1545 }
1546 .into_active_model(),
1547 fruit::ActiveModel {
1548 id: NotSet,
1549 name: Set("Apple".to_owned()),
1550 cake_id: Set(None),
1551 }
1552 );
1553 }
1554
1555 #[test]
1556 #[cfg(feature = "macros")]
1557 fn test_derive_into_active_model_set_multiple() {
1558 use crate as sea_orm;
1559 use crate::entity::prelude::*;
1560
1561 #[derive(DeriveIntoActiveModel)]
1562 #[sea_orm(
1563 active_model = "fruit::ActiveModel",
1564 set(name = "String::from(\"cherry\")", cake_id = "None")
1565 )]
1566 struct IdOnlyFruit {
1567 id: i32,
1568 }
1569 assert_eq!(
1570 IdOnlyFruit { id: 1 }.into_active_model(),
1571 fruit::ActiveModel {
1572 id: Set(1),
1573 name: Set("cherry".to_owned()),
1574 cake_id: Set(None),
1575 }
1576 );
1577
1578 #[derive(DeriveIntoActiveModel)]
1579 #[sea_orm(
1580 active_model = "fruit::ActiveModel",
1581 set(name = "String::from(\"cherry\")"),
1582 set(cake_id = "None")
1583 )]
1584 struct IdOnlyFruit2 {
1585 id: i32,
1586 }
1587 assert_eq!(
1588 IdOnlyFruit2 { id: 1 }.into_active_model(),
1589 fruit::ActiveModel {
1590 id: Set(1),
1591 name: Set("cherry".to_owned()),
1592 cake_id: Set(None),
1593 }
1594 );
1595 }
1596
1597 #[test]
1598 #[cfg(feature = "macros")]
1599 fn test_derive_into_active_model_set_separate_attrs() {
1600 use crate as sea_orm;
1601 use crate::entity::prelude::*;
1602
1603 #[derive(DeriveIntoActiveModel)]
1604 #[sea_orm(
1605 active_model = "fruit::ActiveModel",
1606 set(name = "String::from(\"cherry\")")
1607 )]
1608 #[sea_orm(set(cake_id = "None"))]
1609 struct IdOnlyFruit {
1610 id: i32,
1611 }
1612
1613 assert_eq!(
1614 IdOnlyFruit { id: 1 }.into_active_model(),
1615 fruit::ActiveModel {
1616 id: Set(1),
1617 name: Set("cherry".to_owned()),
1618 cake_id: Set(None),
1619 }
1620 );
1621 }
1622
1623 #[test]
1624 #[cfg(feature = "macros")]
1625 fn test_derive_into_active_model_ignore() {
1626 use crate as sea_orm;
1627 use crate::entity::prelude::*;
1628
1629 #[derive(DeriveIntoActiveModel)]
1630 #[sea_orm(active_model = "fruit::ActiveModel")]
1631 struct NewFruit {
1632 name: String,
1633 cake_id: i32,
1634 #[sea_orm(ignore)]
1635 _extra: String,
1636 }
1637
1638 assert_eq!(
1639 NewFruit {
1640 name: "Apple".to_owned(),
1641 cake_id: 1,
1642 _extra: "ignored".to_owned(),
1643 }
1644 .into_active_model(),
1645 fruit::ActiveModel {
1646 id: NotSet,
1647 name: Set("Apple".to_owned()),
1648 cake_id: Set(Some(1)),
1649 }
1650 );
1651 }
1652
1653 #[test]
1654 #[cfg(feature = "macros")]
1655 fn test_derive_into_active_model_skip() {
1656 use crate as sea_orm;
1657 use crate::entity::prelude::*;
1658
1659 #[derive(DeriveIntoActiveModel)]
1660 #[sea_orm(active_model = "fruit::ActiveModel")]
1661 struct NewFruit {
1662 name: String,
1663 #[sea_orm(skip)]
1664 _extra: String,
1665 }
1666
1667 assert_eq!(
1668 NewFruit {
1669 name: "Apple".to_owned(),
1670 _extra: "skipped".to_owned(),
1671 }
1672 .into_active_model(),
1673 fruit::ActiveModel {
1674 id: NotSet,
1675 name: Set("Apple".to_owned()),
1676 cake_id: NotSet,
1677 }
1678 );
1679 }
1680
1681 #[test]
1682 #[cfg(feature = "macros")]
1683 fn test_derive_into_active_model_set_and_ignore() {
1684 use crate as sea_orm;
1685 use crate::entity::prelude::*;
1686
1687 #[derive(DeriveIntoActiveModel)]
1688 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
1689 struct NewFruit {
1690 name: String,
1691 #[sea_orm(ignore)]
1692 _extra: String,
1693 }
1694
1695 assert_eq!(
1696 NewFruit {
1697 name: "Apple".to_owned(),
1698 _extra: "ignored".to_owned(),
1699 }
1700 .into_active_model(),
1701 fruit::ActiveModel {
1702 id: NotSet,
1703 name: Set("Apple".to_owned()),
1704 cake_id: Set(Some(42)),
1705 }
1706 );
1707 }
1708
1709 #[test]
1710 #[cfg(feature = "macros")]
1711 fn test_derive_into_active_model_foreign_ignore() {
1712 use serde::{Deserialize, Serialize};
1713
1714 use crate as sea_orm;
1715 use crate::entity::prelude::*;
1716
1717 #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
1718 #[sea_orm(active_model = "fruit::ActiveModel")]
1719 struct NewFruit {
1720 #[sea_orm(ignore)]
1721 id: i32,
1722 name: String,
1723 #[serde(skip)]
1724 cake_id: Option<i32>,
1725 }
1726
1727 assert_eq!(
1728 NewFruit {
1729 id: 1.to_owned(),
1730 name: "Apple".to_owned(),
1731 cake_id: Some(42)
1732 }
1733 .into_active_model(),
1734 fruit::ActiveModel {
1735 id: NotSet,
1736 name: Set("Apple".to_owned()),
1737 cake_id: Set(Some(42)),
1738 }
1739 );
1740 }
1741
1742 #[test]
1743 #[cfg(feature = "macros")]
1744 fn test_derive_into_active_model_exhaustive() {
1745 use crate as sea_orm;
1746 use crate::entity::prelude::*;
1747
1748 #[derive(DeriveIntoActiveModel)]
1749 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1750 struct FullFruit {
1751 id: i32,
1752 name: String,
1753 }
1754
1755 assert_eq!(
1756 FullFruit {
1757 id: 1,
1758 name: "Apple".to_owned(),
1759 }
1760 .into_active_model(),
1761 fruit::ActiveModel {
1762 id: Set(1),
1763 name: Set("Apple".to_owned()),
1764 cake_id: Set(None),
1765 }
1766 );
1767 }
1768
1769 #[test]
1770 #[cfg(feature = "macros")]
1771 fn test_derive_into_active_model_multiple_sets() {
1772 use crate as sea_orm;
1773 use crate::entity::prelude::*;
1774
1775 const DEFULT_CAKE_ID: i32 = 1;
1776 #[derive(DeriveIntoActiveModel)]
1777 #[sea_orm(
1778 active_model = "fruit::ActiveModel",
1779 exhaustive,
1780 set(cake_id = "Some(DEFULT_CAKE_ID)")
1781 )]
1782 struct FullFruit {
1783 id: i32,
1784 name: String,
1785 }
1786
1787 assert_eq!(
1788 FullFruit {
1789 id: 1,
1790 name: "Apple".to_owned(),
1791 }
1792 .into_active_model(),
1793 fruit::ActiveModel {
1794 id: Set(1),
1795 name: Set("Apple".to_owned()),
1796 cake_id: Set(Some(1)),
1797 }
1798 );
1799 }
1800
1801 #[test]
1802 #[cfg(feature = "macros")]
1803 fn test_derive_into_active_model_field_empty_default() {
1804 use crate as sea_orm;
1805 use crate::entity::prelude::*;
1806
1807 #[derive(DeriveIntoActiveModel)]
1808 #[sea_orm(active_model = "fruit::ActiveModel")]
1809 struct NewFruit {
1810 #[sea_orm(default)]
1811 name: Option<String>,
1812 }
1813
1814 assert_eq!(
1816 NewFruit {
1817 name: Some("Apple".to_owned()),
1818 }
1819 .into_active_model(),
1820 fruit::ActiveModel {
1821 id: NotSet,
1822 name: Set("Apple".to_owned()),
1823 cake_id: NotSet,
1824 }
1825 );
1826
1827 assert_eq!(
1829 NewFruit { name: None }.into_active_model(),
1830 fruit::ActiveModel {
1831 id: NotSet,
1832 name: Set("".to_owned()),
1833 cake_id: NotSet,
1834 }
1835 );
1836 }
1837
1838 #[test]
1839 #[cfg(feature = "macros")]
1840 fn test_derive_into_active_model_field_custom_option() {
1841 use crate as sea_orm;
1842 use crate::entity::prelude::*;
1843 mod foreign_crate {
1844 #[derive(Debug, Clone, PartialEq, Eq)]
1845 pub enum CustomOption<T> {
1846 None,
1847 Some(T),
1848 }
1849
1850 impl From<CustomOption<String>> for Option<String> {
1851 fn from(option: CustomOption<String>) -> Self {
1852 match option {
1853 CustomOption::None => Option::None,
1854 CustomOption::Some(value) => value.into(),
1855 }
1856 }
1857 }
1858 }
1859 use foreign_crate::CustomOption;
1860
1861 #[derive(DeriveIntoActiveModel)]
1862 #[sea_orm(active_model = "fruit::ActiveModel")]
1863 struct NewFruit {
1864 #[sea_orm(default)]
1865 name: CustomOption<String>,
1866 }
1867
1868 assert_eq!(
1870 NewFruit {
1871 name: CustomOption::Some("Apple".to_owned()),
1872 }
1873 .into_active_model(),
1874 fruit::ActiveModel {
1875 id: NotSet,
1876 name: Set("Apple".to_owned()),
1877 cake_id: NotSet,
1878 }
1879 );
1880
1881 assert_eq!(
1883 NewFruit {
1884 name: CustomOption::None
1885 }
1886 .into_active_model(),
1887 fruit::ActiveModel {
1888 id: NotSet,
1889 name: Set("".to_owned()),
1890 cake_id: NotSet,
1891 }
1892 );
1893 }
1894
1895 #[test]
1896 #[cfg(feature = "macros")]
1897 fn test_derive_into_active_model_field_default_some() {
1898 use crate as sea_orm;
1899 use crate::entity::prelude::*;
1900
1901 #[derive(DeriveIntoActiveModel)]
1902 #[sea_orm(active_model = "fruit::ActiveModel")]
1903 struct NewFruit {
1904 #[sea_orm(default = "String::from(\"Unnamed\")")]
1905 name: Option<String>,
1906 }
1907
1908 assert_eq!(
1910 NewFruit {
1911 name: Some("Apple".to_owned()),
1912 }
1913 .into_active_model(),
1914 fruit::ActiveModel {
1915 id: NotSet,
1916 name: Set("Apple".to_owned()),
1917 cake_id: NotSet,
1918 }
1919 );
1920
1921 assert_eq!(
1923 NewFruit { name: None }.into_active_model(),
1924 fruit::ActiveModel {
1925 id: NotSet,
1926 name: Set("Unnamed".to_owned()),
1927 cake_id: NotSet,
1928 }
1929 );
1930 }
1931
1932 #[test]
1933 #[cfg(feature = "macros")]
1934 fn test_derive_into_active_model_field_default_with_set() {
1935 use crate as sea_orm;
1936 use crate::entity::prelude::*;
1937
1938 #[derive(DeriveIntoActiveModel)]
1939 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
1940 struct NewFruit {
1941 #[sea_orm(default = "String::from(\"Unnamed\")")]
1942 name: Option<String>,
1943 #[sea_orm(ignore)]
1944 _extra: String,
1945 }
1946
1947 assert_eq!(
1948 NewFruit {
1949 name: Some("Apple".to_owned()),
1950 _extra: "ignored".to_owned(),
1951 }
1952 .into_active_model(),
1953 fruit::ActiveModel {
1954 id: NotSet,
1955 name: Set("Apple".to_owned()),
1956 cake_id: Set(Some(99)),
1957 }
1958 );
1959
1960 assert_eq!(
1961 NewFruit {
1962 name: None,
1963 _extra: "ignored".to_owned(),
1964 }
1965 .into_active_model(),
1966 fruit::ActiveModel {
1967 id: NotSet,
1968 name: Set("Unnamed".to_owned()),
1969 cake_id: Set(Some(99)),
1970 }
1971 );
1972 }
1973
1974 #[test]
1975 #[cfg(feature = "macros")]
1976 fn test_derive_into_active_model_field_default_exhaustive() {
1977 use crate as sea_orm;
1978 use crate::entity::prelude::*;
1979
1980 #[derive(DeriveIntoActiveModel)]
1981 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1982 struct NewFruit {
1983 id: i32,
1984 #[sea_orm(default = "String::from(\"Unnamed\")")]
1985 name: Option<String>,
1986 }
1987
1988 assert_eq!(
1989 NewFruit {
1990 id: 1,
1991 name: Some("Apple".to_owned()),
1992 }
1993 .into_active_model(),
1994 fruit::ActiveModel {
1995 id: Set(1),
1996 name: Set("Apple".to_owned()),
1997 cake_id: Set(None),
1998 }
1999 );
2000
2001 assert_eq!(
2002 NewFruit { id: 2, name: None }.into_active_model(),
2003 fruit::ActiveModel {
2004 id: Set(2),
2005 name: Set("Unnamed".to_owned()),
2006 cake_id: Set(None),
2007 }
2008 );
2009 }
2010
2011 #[test]
2012 #[cfg(feature = "macros")]
2013 fn test_derive_try_into_model_1() {
2014 mod my_fruit {
2015 use crate as sea_orm;
2016 use crate::entity::prelude::*;
2017
2018 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2019 #[sea_orm(table_name = "fruit")]
2020 pub struct Model {
2021 #[sea_orm(primary_key)]
2022 pub id: i32,
2023 pub name: String,
2024 pub cake_id: Option<i32>,
2025 }
2026
2027 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2028 pub enum Relation {}
2029
2030 impl ActiveModelBehavior for ActiveModel {}
2031 }
2032 assert_eq!(
2033 my_fruit::ActiveModel {
2034 id: Set(1),
2035 name: Set("Pineapple".to_owned()),
2036 cake_id: Set(None),
2037 }
2038 .try_into_model()
2039 .unwrap(),
2040 my_fruit::Model {
2041 id: 1,
2042 name: "Pineapple".to_owned(),
2043 cake_id: None,
2044 }
2045 );
2046
2047 assert_eq!(
2048 my_fruit::ActiveModel {
2049 id: Set(2),
2050 name: Set("Apple".to_owned()),
2051 cake_id: Set(Some(1)),
2052 }
2053 .try_into_model()
2054 .unwrap(),
2055 my_fruit::Model {
2056 id: 2,
2057 name: "Apple".to_owned(),
2058 cake_id: Some(1),
2059 }
2060 );
2061
2062 assert_eq!(
2063 my_fruit::ActiveModel {
2064 id: Set(1),
2065 name: NotSet,
2066 cake_id: Set(None),
2067 }
2068 .try_into_model(),
2069 Err(DbErr::AttrNotSet(String::from("name")))
2070 );
2071
2072 assert_eq!(
2073 my_fruit::ActiveModel {
2074 id: Set(1),
2075 name: Set("Pineapple".to_owned()),
2076 cake_id: NotSet,
2077 }
2078 .try_into_model(),
2079 Err(DbErr::AttrNotSet(String::from("cake_id")))
2080 );
2081 }
2082
2083 #[test]
2084 #[cfg(feature = "macros")]
2085 fn test_derive_try_into_model_2() {
2086 mod my_fruit {
2087 use crate as sea_orm;
2088 use crate::entity::prelude::*;
2089
2090 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2091 #[sea_orm(table_name = "fruit")]
2092 pub struct Model {
2093 #[sea_orm(primary_key)]
2094 pub id: i32,
2095 pub name: String,
2096 #[sea_orm(ignore)]
2097 pub cake_id: Option<i32>,
2098 }
2099
2100 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2101 pub enum Relation {}
2102
2103 impl ActiveModelBehavior for ActiveModel {}
2104 }
2105 assert_eq!(
2106 my_fruit::ActiveModel {
2107 id: Set(1),
2108 name: Set("Pineapple".to_owned()),
2109 }
2110 .try_into_model()
2111 .unwrap(),
2112 my_fruit::Model {
2113 id: 1,
2114 name: "Pineapple".to_owned(),
2115 cake_id: None,
2116 }
2117 );
2118 }
2119
2120 #[test]
2121 #[cfg(feature = "macros")]
2122 fn test_derive_try_into_model_3() {
2123 mod my_fruit {
2124 use crate as sea_orm;
2125 use crate::entity::prelude::*;
2126
2127 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2128 #[sea_orm(table_name = "fruit")]
2129 pub struct Model {
2130 #[sea_orm(primary_key)]
2131 pub id: i32,
2132 #[sea_orm(ignore)]
2133 pub name: String,
2134 pub cake_id: Option<i32>,
2135 }
2136
2137 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2138 pub enum Relation {}
2139
2140 impl ActiveModelBehavior for ActiveModel {}
2141 }
2142 assert_eq!(
2143 my_fruit::ActiveModel {
2144 id: Set(1),
2145 cake_id: Set(Some(1)),
2146 }
2147 .try_into_model()
2148 .unwrap(),
2149 my_fruit::Model {
2150 id: 1,
2151 name: "".to_owned(),
2152 cake_id: Some(1),
2153 }
2154 );
2155 }
2156
2157 #[test]
2158 #[cfg(feature = "with-json")]
2159 fn test_active_model_set_from_json_1() {
2160 assert_eq!(
2161 cake::ActiveModel::from_json(json!({
2162 "id": 1,
2163 "name": "Apple Pie",
2164 }))
2165 .unwrap(),
2166 cake::ActiveModel {
2167 id: Set(1),
2168 name: Set("Apple Pie".to_owned()),
2169 }
2170 );
2171
2172 assert_eq!(
2173 cake::ActiveModel::from_json(json!({
2174 "id": 1,
2175 }))
2176 .unwrap(),
2177 cake::ActiveModel {
2178 id: Set(1),
2179 name: NotSet,
2180 }
2181 );
2182
2183 assert_eq!(
2184 cake::ActiveModel::from_json(json!({
2185 "name": "Apple Pie",
2186 }))
2187 .unwrap(),
2188 cake::ActiveModel {
2189 id: NotSet,
2190 name: Set("Apple Pie".to_owned()),
2191 }
2192 );
2193
2194 let mut cake: cake::ActiveModel = Default::default();
2195 cake.set_from_json(json!({
2196 "name": "Apple Pie",
2197 }))
2198 .unwrap();
2199 assert_eq!(
2200 cake,
2201 cake::ActiveModel {
2202 id: NotSet,
2203 name: Set("Apple Pie".to_owned()),
2204 }
2205 );
2206 }
2207
2208 #[test]
2209 #[cfg(feature = "with-json")]
2210 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
2211 let mut fruit: fruit::ActiveModel = Default::default();
2212
2213 fruit.set_from_json(json!({
2214 "name": "Apple",
2215 }))?;
2216 assert_eq!(
2217 fruit,
2218 fruit::ActiveModel {
2219 id: ActiveValue::NotSet,
2220 name: ActiveValue::Set("Apple".to_owned()),
2221 cake_id: ActiveValue::NotSet,
2222 }
2223 );
2224
2225 assert_eq!(
2226 fruit::ActiveModel::from_json(json!({
2227 "name": "Apple",
2228 }))?,
2229 fruit::ActiveModel {
2230 id: ActiveValue::NotSet,
2231 name: ActiveValue::Set("Apple".to_owned()),
2232 cake_id: ActiveValue::NotSet,
2233 }
2234 );
2235
2236 fruit.set_from_json(json!({
2237 "name": "Apple",
2238 "cake_id": null,
2239 }))?;
2240 assert_eq!(
2241 fruit,
2242 fruit::ActiveModel {
2243 id: ActiveValue::NotSet,
2244 name: ActiveValue::Set("Apple".to_owned()),
2245 cake_id: ActiveValue::Set(None),
2246 }
2247 );
2248
2249 fruit.set_from_json(json!({
2250 "id": null,
2251 "name": "Apple",
2252 "cake_id": 1,
2253 }))?;
2254 assert_eq!(
2255 fruit,
2256 fruit::ActiveModel {
2257 id: ActiveValue::NotSet,
2258 name: ActiveValue::Set("Apple".to_owned()),
2259 cake_id: ActiveValue::Set(Some(1)),
2260 }
2261 );
2262
2263 fruit.set_from_json(json!({
2264 "id": 2,
2265 "name": "Apple",
2266 "cake_id": 1,
2267 }))?;
2268 assert_eq!(
2269 fruit,
2270 fruit::ActiveModel {
2271 id: ActiveValue::NotSet,
2272 name: ActiveValue::Set("Apple".to_owned()),
2273 cake_id: ActiveValue::Set(Some(1)),
2274 }
2275 );
2276
2277 let mut fruit = fruit::ActiveModel {
2278 id: ActiveValue::Set(1),
2279 name: ActiveValue::NotSet,
2280 cake_id: ActiveValue::NotSet,
2281 };
2282 fruit.set_from_json(json!({
2283 "id": 8,
2284 "name": "Apple",
2285 "cake_id": 1,
2286 }))?;
2287 assert_eq!(
2288 fruit,
2289 fruit::ActiveModel {
2290 id: ActiveValue::Set(1),
2291 name: ActiveValue::Set("Apple".to_owned()),
2292 cake_id: ActiveValue::Set(Some(1)),
2293 }
2294 );
2295
2296 Ok(())
2297 }
2298
2299 #[test]
2300 #[cfg(feature = "with-json")]
2301 fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
2302 use crate::*;
2303
2304 let db = MockDatabase::new(DbBackend::Postgres)
2305 .append_exec_results([
2306 MockExecResult {
2307 last_insert_id: 1,
2308 rows_affected: 1,
2309 },
2310 MockExecResult {
2311 last_insert_id: 1,
2312 rows_affected: 1,
2313 },
2314 ])
2315 .append_query_results([
2316 [fruit::Model {
2317 id: 1,
2318 name: "Apple".to_owned(),
2319 cake_id: None,
2320 }],
2321 [fruit::Model {
2322 id: 2,
2323 name: "Orange".to_owned(),
2324 cake_id: Some(1),
2325 }],
2326 ])
2327 .into_connection();
2328
2329 let mut fruit: fruit::ActiveModel = Default::default();
2330 fruit.set_from_json(json!({
2331 "name": "Apple",
2332 }))?;
2333 fruit.save(&db)?;
2334
2335 let mut fruit = fruit::ActiveModel {
2336 id: Set(2),
2337 ..Default::default()
2338 };
2339 fruit.set_from_json(json!({
2340 "id": 9,
2341 "name": "Orange",
2342 "cake_id": 1,
2343 }))?;
2344 fruit.save(&db)?;
2345
2346 assert_eq!(
2347 db.into_transaction_log(),
2348 [
2349 Transaction::from_sql_and_values(
2350 DbBackend::Postgres,
2351 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
2352 ["Apple".into()],
2353 ),
2354 Transaction::from_sql_and_values(
2355 DbBackend::Postgres,
2356 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2357 ["Orange".into(), 1i32.into(), 2i32.into()],
2358 ),
2359 ]
2360 );
2361
2362 Ok(())
2363 }
2364
2365 #[test]
2366 fn test_active_model_is_changed() {
2367 let mut fruit: fruit::ActiveModel = Default::default();
2368 assert!(!fruit.is_changed());
2369
2370 fruit.set(fruit::Column::Name, "apple".into());
2371 assert!(fruit.is_changed());
2372
2373 let mut fruit = fruit::Model {
2374 id: 1,
2375 name: "".into(),
2376 cake_id: None,
2377 };
2378 fruit.set("name".parse().unwrap(), "orange".into());
2379 assert_eq!(fruit.name, "orange");
2380 }
2381
2382 #[test]
2383 fn test_reset_1() {
2384 assert_eq!(
2385 fruit::Model {
2386 id: 1,
2387 name: "Apple".into(),
2388 cake_id: None,
2389 }
2390 .into_active_model(),
2391 fruit::ActiveModel {
2392 id: Unchanged(1),
2393 name: Unchanged("Apple".into()),
2394 cake_id: Unchanged(None)
2395 },
2396 );
2397
2398 assert_eq!(
2399 fruit::Model {
2400 id: 1,
2401 name: "Apple".into(),
2402 cake_id: None,
2403 }
2404 .into_active_model()
2405 .reset_all(),
2406 fruit::ActiveModel {
2407 id: Set(1),
2408 name: Set("Apple".into()),
2409 cake_id: Set(None)
2410 },
2411 );
2412
2413 assert_eq!(
2414 fruit::Model {
2415 id: 1,
2416 name: "Apple".into(),
2417 cake_id: Some(2),
2418 }
2419 .into_active_model(),
2420 fruit::ActiveModel {
2421 id: Unchanged(1),
2422 name: Unchanged("Apple".into()),
2423 cake_id: Unchanged(Some(2)),
2424 },
2425 );
2426
2427 assert_eq!(
2428 fruit::Model {
2429 id: 1,
2430 name: "Apple".into(),
2431 cake_id: Some(2),
2432 }
2433 .into_active_model()
2434 .reset_all(),
2435 fruit::ActiveModel {
2436 id: Set(1),
2437 name: Set("Apple".into()),
2438 cake_id: Set(Some(2)),
2439 },
2440 );
2441 }
2442
2443 #[test]
2444 fn test_reset_2() -> Result<(), DbErr> {
2445 use crate::*;
2446
2447 let db = MockDatabase::new(DbBackend::Postgres)
2448 .append_exec_results(vec![
2449 MockExecResult {
2450 last_insert_id: 1,
2451 rows_affected: 1,
2452 },
2453 MockExecResult {
2454 last_insert_id: 1,
2455 rows_affected: 1,
2456 },
2457 ])
2458 .append_query_results(vec![
2459 vec![fruit::Model {
2460 id: 1,
2461 name: "Apple".to_owned(),
2462 cake_id: None,
2463 }],
2464 vec![fruit::Model {
2465 id: 1,
2466 name: "Apple".to_owned(),
2467 cake_id: None,
2468 }],
2469 ])
2470 .into_connection();
2471
2472 fruit::Model {
2473 id: 1,
2474 name: "Apple".into(),
2475 cake_id: None,
2476 }
2477 .into_active_model()
2478 .update(&db)?;
2479
2480 fruit::Model {
2481 id: 1,
2482 name: "Apple".into(),
2483 cake_id: None,
2484 }
2485 .into_active_model()
2486 .reset_all()
2487 .update(&db)?;
2488
2489 assert_eq!(
2490 db.into_transaction_log(),
2491 vec![
2492 Transaction::from_sql_and_values(
2493 DbBackend::Postgres,
2494 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
2495 vec![1i32.into(), 1u64.into()],
2496 ),
2497 Transaction::from_sql_and_values(
2498 DbBackend::Postgres,
2499 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2500 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
2501 ),
2502 ]
2503 );
2504
2505 Ok(())
2506 }
2507
2508 #[test]
2509 fn test_active_model_default_values() {
2510 assert_eq!(
2511 fruit::ActiveModel::default_values(),
2512 fruit::ActiveModel {
2513 id: Set(0),
2514 name: Set("".into()),
2515 cake_id: Set(None),
2516 },
2517 );
2518
2519 assert_eq!(
2520 lunch_set::ActiveModel::default_values(),
2521 lunch_set::ActiveModel {
2522 id: Set(0),
2523 name: Set("".into()),
2524 tea: NotSet,
2525 },
2526 );
2527 }
2528
2529 #[test]
2530 fn test_active_model_set_parent_key() {
2531 let mut fruit = fruit::Model {
2532 id: 2,
2533 name: "F".into(),
2534 cake_id: None,
2535 }
2536 .into_active_model();
2537
2538 let cake = cake::Model {
2539 id: 4,
2540 name: "C".into(),
2541 }
2542 .into_active_model();
2543
2544 fruit.set_parent_key(&cake).unwrap();
2545
2546 assert_eq!(
2547 fruit,
2548 fruit::ActiveModel {
2549 id: Unchanged(2),
2550 name: Unchanged("F".into()),
2551 cake_id: Set(Some(4)),
2552 }
2553 );
2554
2555 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
2556
2557 assert_eq!(
2558 fruit,
2559 fruit::ActiveModel {
2560 id: Unchanged(2),
2561 name: Unchanged("F".into()),
2562 cake_id: Set(None),
2563 }
2564 );
2565
2566 let mut cake_filling = cake_filling::ActiveModel::new();
2567
2568 cake_filling.set_parent_key(&cake).unwrap();
2569
2570 assert_eq!(
2571 cake_filling,
2572 cake_filling::ActiveModel {
2573 cake_id: Set(4),
2574 filling_id: NotSet,
2575 }
2576 );
2577 }
2578}