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