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)]
902 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
903 where
904 AM: ActiveModelTrait,
905 Self::Entity: Related<AM::Entity>,
906 {
907 self.find_related(AM::Entity::default())
908 }
909
910 #[doc(hidden)]
913 async fn establish_links<J, R, RM, C>(
914 &self,
915 _: J,
916 related_models: &[RM],
917 delete_leftover: bool,
918 db: &C,
919 ) -> Result<(), DbErr>
920 where
921 R: EntityTrait,
922 RM: ActiveModelTrait<Entity = R> + Sync,
923 J: EntityTrait + Related<R> + Related<Self::Entity>,
924 J::Model: IntoActiveModel<J::ActiveModel>,
925 J::ActiveModel: ActiveModelBehavior + Send,
926 C: ConnectionTrait,
927 {
928 let left = <J as Related<Self::Entity>>::to();
929 let right = <J as Related<R>>::to();
930
931 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
932 }
933
934 #[doc(hidden)]
936 async fn establish_links_self<J, RM, C>(
937 &self,
938 _: J,
939 related_models: &[RM],
940 delete_leftover: bool,
941 db: &C,
942 ) -> Result<(), DbErr>
943 where
944 RM: ActiveModelTrait<Entity = Self::Entity> + Sync,
945 J: EntityTrait,
946 J::Model: IntoActiveModel<J::ActiveModel>,
947 J::ActiveModel: ActiveModelBehavior + Send,
948 C: ConnectionTrait,
949 Self::Entity: RelatedSelfVia<J>,
950 {
951 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
952 let right = <Self::Entity as RelatedSelfVia<J>>::to();
953
954 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
955 }
956
957 #[doc(hidden)]
959 async fn establish_links_self_rev<J, RM, C>(
960 &self,
961 _: J,
962 related_models: &[RM],
963 delete_leftover: bool,
964 db: &C,
965 ) -> Result<(), DbErr>
966 where
967 RM: ActiveModelTrait<Entity = Self::Entity> + Sync,
968 J: EntityTrait,
969 J::Model: IntoActiveModel<J::ActiveModel>,
970 J::ActiveModel: ActiveModelBehavior + Send,
971 C: ConnectionTrait,
972 Self::Entity: RelatedSelfVia<J>,
973 {
974 let left = <Self::Entity as RelatedSelfVia<J>>::to();
975 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
976
977 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
978 }
979
980 #[doc(hidden)]
982 async fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
983 where
984 J: EntityTrait + Related<Self::Entity>,
985 C: ConnectionTrait,
986 {
987 let rel_def = <J as Related<Self::Entity>>::to();
988 let id = get_key_from_active_model(&rel_def.to_col, self)?;
989
990 J::delete_many()
991 .filter(
992 column_tuple_in_condition(
993 &rel_def.from_tbl,
994 &rel_def.from_col,
995 &[id],
996 db.get_database_backend(),
997 )
998 .expect(""),
999 )
1000 .exec(db)
1001 .await
1002 }
1003
1004 #[doc(hidden)]
1006 async fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
1007 where
1008 J: EntityTrait,
1009 C: ConnectionTrait,
1010 Self::Entity: RelatedSelfVia<J>,
1011 {
1012 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
1013 let right = <Self::Entity as RelatedSelfVia<J>>::to();
1014
1015 let id = get_key_from_active_model(&left.to_col, self)?;
1016
1017 if left.to_col != right.to_col {
1018 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
1019 }
1020
1021 J::delete_many()
1022 .filter(
1023 Condition::any()
1024 .add(
1025 column_tuple_in_condition(
1026 &left.from_tbl,
1027 &left.from_col,
1028 std::slice::from_ref(&id),
1029 db.get_database_backend(),
1030 )
1031 .expect(""),
1032 )
1033 .add(
1034 column_tuple_in_condition(
1035 &right.from_tbl,
1036 &right.from_col,
1037 std::slice::from_ref(&id),
1038 db.get_database_backend(),
1039 )
1040 .expect(""),
1041 ),
1042 )
1043 .exec(db)
1044 .await
1045 }
1046}
1047
1048#[allow(unused_variables)]
1074#[async_trait::async_trait]
1075pub trait ActiveModelBehavior: ActiveModelTrait {
1076 fn new() -> Self {
1088 <Self as ActiveModelTrait>::default()
1089 }
1090
1091 async fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1094 where
1095 C: ConnectionTrait,
1096 {
1097 Ok(self)
1098 }
1099
1100 async fn after_save<C>(
1103 model: <Self::Entity as EntityTrait>::Model,
1104 db: &C,
1105 insert: bool,
1106 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1107 where
1108 C: ConnectionTrait,
1109 {
1110 Ok(model)
1111 }
1112
1113 async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1115 where
1116 C: ConnectionTrait,
1117 {
1118 Ok(self)
1119 }
1120
1121 async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1123 where
1124 C: ConnectionTrait,
1125 {
1126 Ok(self)
1127 }
1128}
1129
1130pub trait IntoActiveModel<A>
1215where
1216 A: ActiveModelTrait,
1217{
1218 fn into_active_model(self) -> A;
1220}
1221
1222impl<A> IntoActiveModel<A> for A
1223where
1224 A: ActiveModelTrait,
1225{
1226 fn into_active_model(self) -> A {
1227 self
1228 }
1229}
1230
1231async fn establish_links<EM, J, RM, C>(
1232 model: &EM,
1233 related_models: &[RM],
1234 left: RelationDef,
1235 right: RelationDef,
1236 delete_leftover: bool,
1237 db: &C,
1238) -> Result<(), DbErr>
1239where
1240 EM: ActiveModelTrait,
1241 RM: ActiveModelTrait,
1242 J: EntityTrait,
1243 J::Model: IntoActiveModel<J::ActiveModel>,
1244 J::ActiveModel: ActiveModelBehavior + Send,
1245 C: ConnectionTrait,
1246{
1247 let mut require_leftover = true;
1248
1249 if related_models.is_empty() {
1250 require_leftover = false;
1252 }
1253
1254 let primary_key = J::primary_key_identity();
1255 if require_leftover
1256 && primary_key.fully_contains(&left.from_col)
1257 && primary_key.fully_contains(&right.from_col)
1258 {
1259 require_leftover = false;
1262 }
1263
1264 let mut leftover = Vec::new();
1265 if delete_leftover || require_leftover {
1266 for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1267 &left,
1268 model,
1269 db.get_database_backend(),
1270 )?
1271 .all(db)
1272 .await?
1273 {
1274 let item = item.into_active_model();
1275 let key = get_key_from_active_model(&right.from_col, &item)?;
1276 leftover.push((item, key));
1277 }
1278 }
1279 let leftover = leftover; let mut via_models = Vec::new();
1282 let mut all_keys = std::collections::HashSet::new();
1283
1284 for related_model in related_models {
1285 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1286 via.set_parent_key_for_def(model, &left)?;
1287 via.set_parent_key_for_def(related_model, &right)?;
1288 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1289 if !leftover.iter().any(|t| t.1 == via_key) {
1290 via_models.push(via);
1292 }
1293 if delete_leftover {
1294 all_keys.insert(via_key);
1295 }
1296 }
1297
1298 if delete_leftover {
1299 let mut to_delete = Vec::new();
1300 let mut to_delete_am = Vec::new();
1301 for (leftover, key) in leftover {
1302 if !all_keys.contains(&key) {
1303 to_delete.push(
1304 leftover
1305 .get_primary_key_value()
1306 .expect("item is a full model"),
1307 );
1308 to_delete_am.push(leftover);
1309 }
1310 }
1311 if !to_delete.is_empty() {
1312 for am in to_delete_am.clone() {
1314 am.before_delete(db).await?;
1315 }
1316 if db.support_returning() {
1317 let deleted = J::delete_many()
1318 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1319 .exec_with_returning(db)
1320 .await?;
1321 for am in deleted {
1323 let am = am.into_active_model();
1324 let _ = am.after_delete(db).await?;
1325 }
1326 } else {
1327 J::delete_many()
1328 .filter_by_value_tuples(&to_delete, db.get_database_backend())
1329 .exec(db)
1330 .await?;
1331 for am in to_delete_am {
1333 let _ = am.after_delete(db).await?;
1334 }
1335 }
1336 }
1337 }
1338
1339 if !via_models.is_empty() {
1340 let mut via_models_res = Vec::with_capacity(via_models.len());
1342 for am in via_models {
1343 let am = am.before_save(db, true).await?;
1344 via_models_res.push(am);
1345 }
1346
1347 if db.support_returning() {
1349 let res = J::insert_many(via_models_res)
1351 .on_conflict_do_nothing()
1352 .exec_with_returning_many(db)
1353 .await?;
1354 if let TryInsertResult::Inserted(inserted) = res {
1356 for model in inserted {
1357 let _ = J::ActiveModel::after_save(model, db, true).await?;
1358 }
1359 }
1360 } else {
1361 for model in via_models_res {
1363 let res = J::insert(model)
1364 .on_conflict_do_nothing()
1365 .exec_with_returning(db)
1366 .await?;
1367 if let TryInsertResult::Inserted(model) = res {
1368 let _ = J::ActiveModel::after_save(model, db, true).await?;
1369 }
1370 }
1371 }
1372 }
1373
1374 Ok(())
1375}
1376
1377#[cfg(test)]
1378mod tests {
1379 use crate::{DbErr, entity::*, tests_cfg::*};
1380 use pretty_assertions::assert_eq;
1381
1382 #[cfg(feature = "with-json")]
1383 use serde_json::json;
1384
1385 #[test]
1386 #[cfg(feature = "macros")]
1387 fn test_derive_into_active_model_1() {
1388 mod my_fruit {
1389 pub use super::fruit::*;
1390 use crate as sea_orm;
1391 use crate::entity::prelude::*;
1392
1393 #[derive(DeriveIntoActiveModel)]
1394 pub struct NewFruit {
1395 pub name: String,
1397 pub cake_id: i32,
1399 }
1400 }
1401
1402 assert_eq!(
1403 my_fruit::NewFruit {
1404 name: "Apple".to_owned(),
1405 cake_id: 1,
1406 }
1407 .into_active_model(),
1408 fruit::ActiveModel {
1409 id: NotSet,
1410 name: Set("Apple".to_owned()),
1411 cake_id: Set(Some(1)),
1412 }
1413 );
1414 }
1415
1416 #[test]
1417 #[cfg(feature = "macros")]
1418 fn test_derive_into_active_model_2() {
1419 use crate as sea_orm;
1420 use crate::entity::prelude::*;
1421
1422 #[derive(DeriveIntoActiveModel)]
1423 #[sea_orm(active_model = "fruit::ActiveModel")]
1424 struct RequiredFruitName {
1425 name: String,
1426 }
1427
1428 assert_eq!(
1429 RequiredFruitName {
1430 name: "Apple Pie".to_owned(),
1431 }
1432 .into_active_model(),
1433 fruit::ActiveModel {
1434 id: NotSet,
1435 name: Set("Apple Pie".to_owned()),
1436 cake_id: NotSet,
1437 }
1438 );
1439
1440 #[derive(DeriveIntoActiveModel)]
1441 #[sea_orm(active_model = "fruit::ActiveModel")]
1442 struct OptionalFruitName {
1443 name: Option<String>,
1444 }
1445
1446 assert_eq!(
1447 OptionalFruitName {
1448 name: Some("Apple Pie".to_owned()),
1449 }
1450 .into_active_model(),
1451 fruit::ActiveModel {
1452 id: NotSet,
1453 name: Set("Apple Pie".to_owned()),
1454 cake_id: NotSet,
1455 }
1456 );
1457
1458 assert_eq!(
1459 OptionalFruitName { name: None }.into_active_model(),
1460 fruit::ActiveModel {
1461 id: NotSet,
1462 name: NotSet,
1463 cake_id: NotSet,
1464 }
1465 );
1466
1467 #[derive(DeriveIntoActiveModel)]
1468 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1469 struct RequiredAndNotNullFruitCake {
1470 cake_id: i32,
1471 }
1472
1473 assert_eq!(
1474 RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1475 fruit::ActiveModel {
1476 id: NotSet,
1477 name: NotSet,
1478 cake_id: Set(Some(1)),
1479 }
1480 );
1481
1482 #[derive(DeriveIntoActiveModel)]
1483 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1484 struct OptionalAndNotNullFruitCake {
1485 cake_id: Option<i32>,
1486 }
1487
1488 assert_eq!(
1489 OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1490 fruit::ActiveModel {
1491 id: NotSet,
1492 name: NotSet,
1493 cake_id: Set(Some(1)),
1494 }
1495 );
1496
1497 assert_eq!(
1498 OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1499 fruit::ActiveModel {
1500 id: NotSet,
1501 name: NotSet,
1502 cake_id: NotSet,
1503 }
1504 );
1505
1506 #[derive(DeriveIntoActiveModel)]
1507 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1508 struct OptionalAndNullableFruitCake {
1509 cake_id: Option<Option<i32>>,
1510 }
1511
1512 assert_eq!(
1513 OptionalAndNullableFruitCake {
1514 cake_id: Some(Some(1)),
1515 }
1516 .into_active_model(),
1517 fruit::ActiveModel {
1518 id: NotSet,
1519 name: NotSet,
1520 cake_id: Set(Some(1)),
1521 }
1522 );
1523
1524 assert_eq!(
1525 OptionalAndNullableFruitCake {
1526 cake_id: Some(None),
1527 }
1528 .into_active_model(),
1529 fruit::ActiveModel {
1530 id: NotSet,
1531 name: NotSet,
1532 cake_id: Set(None),
1533 }
1534 );
1535
1536 assert_eq!(
1537 OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1538 fruit::ActiveModel {
1539 id: NotSet,
1540 name: NotSet,
1541 cake_id: NotSet,
1542 }
1543 );
1544 }
1545
1546 #[test]
1547 #[cfg(feature = "macros")]
1548 fn test_derive_into_active_model_set_single() {
1549 use crate as sea_orm;
1550 use crate::entity::prelude::*;
1551
1552 #[derive(DeriveIntoActiveModel)]
1553 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1554 struct NewFruit {
1555 name: String,
1556 }
1557
1558 assert_eq!(
1559 NewFruit {
1560 name: "Apple".to_owned(),
1561 }
1562 .into_active_model(),
1563 fruit::ActiveModel {
1564 id: NotSet,
1565 name: Set("Apple".to_owned()),
1566 cake_id: Set(None),
1567 }
1568 );
1569 }
1570
1571 #[test]
1572 #[cfg(feature = "macros")]
1573 fn test_derive_into_active_model_set_multiple() {
1574 use crate as sea_orm;
1575 use crate::entity::prelude::*;
1576
1577 #[derive(DeriveIntoActiveModel)]
1578 #[sea_orm(
1579 active_model = "fruit::ActiveModel",
1580 set(name = "String::from(\"cherry\")", cake_id = "None")
1581 )]
1582 struct IdOnlyFruit {
1583 id: i32,
1584 }
1585 assert_eq!(
1586 IdOnlyFruit { id: 1 }.into_active_model(),
1587 fruit::ActiveModel {
1588 id: Set(1),
1589 name: Set("cherry".to_owned()),
1590 cake_id: Set(None),
1591 }
1592 );
1593
1594 #[derive(DeriveIntoActiveModel)]
1595 #[sea_orm(
1596 active_model = "fruit::ActiveModel",
1597 set(name = "String::from(\"cherry\")"),
1598 set(cake_id = "None")
1599 )]
1600 struct IdOnlyFruit2 {
1601 id: i32,
1602 }
1603 assert_eq!(
1604 IdOnlyFruit2 { id: 1 }.into_active_model(),
1605 fruit::ActiveModel {
1606 id: Set(1),
1607 name: Set("cherry".to_owned()),
1608 cake_id: Set(None),
1609 }
1610 );
1611 }
1612
1613 #[test]
1614 #[cfg(feature = "macros")]
1615 fn test_derive_into_active_model_set_separate_attrs() {
1616 use crate as sea_orm;
1617 use crate::entity::prelude::*;
1618
1619 #[derive(DeriveIntoActiveModel)]
1620 #[sea_orm(
1621 active_model = "fruit::ActiveModel",
1622 set(name = "String::from(\"cherry\")")
1623 )]
1624 #[sea_orm(set(cake_id = "None"))]
1625 struct IdOnlyFruit {
1626 id: i32,
1627 }
1628
1629 assert_eq!(
1630 IdOnlyFruit { id: 1 }.into_active_model(),
1631 fruit::ActiveModel {
1632 id: Set(1),
1633 name: Set("cherry".to_owned()),
1634 cake_id: Set(None),
1635 }
1636 );
1637 }
1638
1639 #[test]
1640 #[cfg(feature = "macros")]
1641 fn test_derive_into_active_model_ignore() {
1642 use crate as sea_orm;
1643 use crate::entity::prelude::*;
1644
1645 #[derive(DeriveIntoActiveModel)]
1646 #[sea_orm(active_model = "fruit::ActiveModel")]
1647 struct NewFruit {
1648 name: String,
1649 cake_id: i32,
1650 #[sea_orm(ignore)]
1651 _extra: String,
1652 }
1653
1654 assert_eq!(
1655 NewFruit {
1656 name: "Apple".to_owned(),
1657 cake_id: 1,
1658 _extra: "ignored".to_owned(),
1659 }
1660 .into_active_model(),
1661 fruit::ActiveModel {
1662 id: NotSet,
1663 name: Set("Apple".to_owned()),
1664 cake_id: Set(Some(1)),
1665 }
1666 );
1667 }
1668
1669 #[test]
1670 #[cfg(feature = "macros")]
1671 fn test_derive_into_active_model_skip() {
1672 use crate as sea_orm;
1673 use crate::entity::prelude::*;
1674
1675 #[derive(DeriveIntoActiveModel)]
1676 #[sea_orm(active_model = "fruit::ActiveModel")]
1677 struct NewFruit {
1678 name: String,
1679 #[sea_orm(skip)]
1680 _extra: String,
1681 }
1682
1683 assert_eq!(
1684 NewFruit {
1685 name: "Apple".to_owned(),
1686 _extra: "skipped".to_owned(),
1687 }
1688 .into_active_model(),
1689 fruit::ActiveModel {
1690 id: NotSet,
1691 name: Set("Apple".to_owned()),
1692 cake_id: NotSet,
1693 }
1694 );
1695 }
1696
1697 #[test]
1698 #[cfg(feature = "macros")]
1699 fn test_derive_into_active_model_set_and_ignore() {
1700 use crate as sea_orm;
1701 use crate::entity::prelude::*;
1702
1703 #[derive(DeriveIntoActiveModel)]
1704 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
1705 struct NewFruit {
1706 name: String,
1707 #[sea_orm(ignore)]
1708 _extra: String,
1709 }
1710
1711 assert_eq!(
1712 NewFruit {
1713 name: "Apple".to_owned(),
1714 _extra: "ignored".to_owned(),
1715 }
1716 .into_active_model(),
1717 fruit::ActiveModel {
1718 id: NotSet,
1719 name: Set("Apple".to_owned()),
1720 cake_id: Set(Some(42)),
1721 }
1722 );
1723 }
1724
1725 #[test]
1726 #[cfg(feature = "macros")]
1727 fn test_derive_into_active_model_foreign_ignore() {
1728 use serde::{Deserialize, Serialize};
1729
1730 use crate as sea_orm;
1731 use crate::entity::prelude::*;
1732
1733 #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
1734 #[sea_orm(active_model = "fruit::ActiveModel")]
1735 struct NewFruit {
1736 #[sea_orm(ignore)]
1737 id: i32,
1738 name: String,
1739 #[serde(skip)]
1740 cake_id: Option<i32>,
1741 }
1742
1743 assert_eq!(
1744 NewFruit {
1745 id: 1.to_owned(),
1746 name: "Apple".to_owned(),
1747 cake_id: Some(42)
1748 }
1749 .into_active_model(),
1750 fruit::ActiveModel {
1751 id: NotSet,
1752 name: Set("Apple".to_owned()),
1753 cake_id: Set(Some(42)),
1754 }
1755 );
1756 }
1757
1758 #[test]
1759 #[cfg(feature = "macros")]
1760 fn test_derive_into_active_model_exhaustive() {
1761 use crate as sea_orm;
1762 use crate::entity::prelude::*;
1763
1764 #[derive(DeriveIntoActiveModel)]
1765 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1766 struct FullFruit {
1767 id: i32,
1768 name: String,
1769 }
1770
1771 assert_eq!(
1772 FullFruit {
1773 id: 1,
1774 name: "Apple".to_owned(),
1775 }
1776 .into_active_model(),
1777 fruit::ActiveModel {
1778 id: Set(1),
1779 name: Set("Apple".to_owned()),
1780 cake_id: Set(None),
1781 }
1782 );
1783 }
1784
1785 #[test]
1786 #[cfg(feature = "macros")]
1787 fn test_derive_into_active_model_multiple_sets() {
1788 use crate as sea_orm;
1789 use crate::entity::prelude::*;
1790
1791 const DEFULT_CAKE_ID: i32 = 1;
1792 #[derive(DeriveIntoActiveModel)]
1793 #[sea_orm(
1794 active_model = "fruit::ActiveModel",
1795 exhaustive,
1796 set(cake_id = "Some(DEFULT_CAKE_ID)")
1797 )]
1798 struct FullFruit {
1799 id: i32,
1800 name: String,
1801 }
1802
1803 assert_eq!(
1804 FullFruit {
1805 id: 1,
1806 name: "Apple".to_owned(),
1807 }
1808 .into_active_model(),
1809 fruit::ActiveModel {
1810 id: Set(1),
1811 name: Set("Apple".to_owned()),
1812 cake_id: Set(Some(1)),
1813 }
1814 );
1815 }
1816
1817 #[test]
1818 #[cfg(feature = "macros")]
1819 fn test_derive_into_active_model_field_empty_default() {
1820 use crate as sea_orm;
1821 use crate::entity::prelude::*;
1822
1823 #[derive(DeriveIntoActiveModel)]
1824 #[sea_orm(active_model = "fruit::ActiveModel")]
1825 struct NewFruit {
1826 #[sea_orm(default)]
1827 name: Option<String>,
1828 }
1829
1830 assert_eq!(
1832 NewFruit {
1833 name: Some("Apple".to_owned()),
1834 }
1835 .into_active_model(),
1836 fruit::ActiveModel {
1837 id: NotSet,
1838 name: Set("Apple".to_owned()),
1839 cake_id: NotSet,
1840 }
1841 );
1842
1843 assert_eq!(
1845 NewFruit { name: None }.into_active_model(),
1846 fruit::ActiveModel {
1847 id: NotSet,
1848 name: Set("".to_owned()),
1849 cake_id: NotSet,
1850 }
1851 );
1852 }
1853
1854 #[test]
1855 #[cfg(feature = "macros")]
1856 fn test_derive_into_active_model_field_custom_option() {
1857 use crate as sea_orm;
1858 use crate::entity::prelude::*;
1859 mod foreign_crate {
1860 #[derive(Debug, Clone, PartialEq, Eq)]
1861 pub enum CustomOption<T> {
1862 None,
1863 Some(T),
1864 }
1865
1866 impl From<CustomOption<String>> for Option<String> {
1867 fn from(option: CustomOption<String>) -> Self {
1868 match option {
1869 CustomOption::None => Option::None,
1870 CustomOption::Some(value) => value.into(),
1871 }
1872 }
1873 }
1874 }
1875 use foreign_crate::CustomOption;
1876
1877 #[derive(DeriveIntoActiveModel)]
1878 #[sea_orm(active_model = "fruit::ActiveModel")]
1879 struct NewFruit {
1880 #[sea_orm(default)]
1881 name: CustomOption<String>,
1882 }
1883
1884 assert_eq!(
1886 NewFruit {
1887 name: CustomOption::Some("Apple".to_owned()),
1888 }
1889 .into_active_model(),
1890 fruit::ActiveModel {
1891 id: NotSet,
1892 name: Set("Apple".to_owned()),
1893 cake_id: NotSet,
1894 }
1895 );
1896
1897 assert_eq!(
1899 NewFruit {
1900 name: CustomOption::None
1901 }
1902 .into_active_model(),
1903 fruit::ActiveModel {
1904 id: NotSet,
1905 name: Set("".to_owned()),
1906 cake_id: NotSet,
1907 }
1908 );
1909 }
1910
1911 #[test]
1912 #[cfg(feature = "macros")]
1913 fn test_derive_into_active_model_field_default_some() {
1914 use crate as sea_orm;
1915 use crate::entity::prelude::*;
1916
1917 #[derive(DeriveIntoActiveModel)]
1918 #[sea_orm(active_model = "fruit::ActiveModel")]
1919 struct NewFruit {
1920 #[sea_orm(default = "String::from(\"Unnamed\")")]
1921 name: Option<String>,
1922 }
1923
1924 assert_eq!(
1926 NewFruit {
1927 name: Some("Apple".to_owned()),
1928 }
1929 .into_active_model(),
1930 fruit::ActiveModel {
1931 id: NotSet,
1932 name: Set("Apple".to_owned()),
1933 cake_id: NotSet,
1934 }
1935 );
1936
1937 assert_eq!(
1939 NewFruit { name: None }.into_active_model(),
1940 fruit::ActiveModel {
1941 id: NotSet,
1942 name: Set("Unnamed".to_owned()),
1943 cake_id: NotSet,
1944 }
1945 );
1946 }
1947
1948 #[test]
1949 #[cfg(feature = "macros")]
1950 fn test_derive_into_active_model_field_default_with_set() {
1951 use crate as sea_orm;
1952 use crate::entity::prelude::*;
1953
1954 #[derive(DeriveIntoActiveModel)]
1955 #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
1956 struct NewFruit {
1957 #[sea_orm(default = "String::from(\"Unnamed\")")]
1958 name: Option<String>,
1959 #[sea_orm(ignore)]
1960 _extra: String,
1961 }
1962
1963 assert_eq!(
1964 NewFruit {
1965 name: Some("Apple".to_owned()),
1966 _extra: "ignored".to_owned(),
1967 }
1968 .into_active_model(),
1969 fruit::ActiveModel {
1970 id: NotSet,
1971 name: Set("Apple".to_owned()),
1972 cake_id: Set(Some(99)),
1973 }
1974 );
1975
1976 assert_eq!(
1977 NewFruit {
1978 name: None,
1979 _extra: "ignored".to_owned(),
1980 }
1981 .into_active_model(),
1982 fruit::ActiveModel {
1983 id: NotSet,
1984 name: Set("Unnamed".to_owned()),
1985 cake_id: Set(Some(99)),
1986 }
1987 );
1988 }
1989
1990 #[test]
1991 #[cfg(feature = "macros")]
1992 fn test_derive_into_active_model_field_default_exhaustive() {
1993 use crate as sea_orm;
1994 use crate::entity::prelude::*;
1995
1996 #[derive(DeriveIntoActiveModel)]
1997 #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1998 struct NewFruit {
1999 id: i32,
2000 #[sea_orm(default = "String::from(\"Unnamed\")")]
2001 name: Option<String>,
2002 }
2003
2004 assert_eq!(
2005 NewFruit {
2006 id: 1,
2007 name: Some("Apple".to_owned()),
2008 }
2009 .into_active_model(),
2010 fruit::ActiveModel {
2011 id: Set(1),
2012 name: Set("Apple".to_owned()),
2013 cake_id: Set(None),
2014 }
2015 );
2016
2017 assert_eq!(
2018 NewFruit { id: 2, name: None }.into_active_model(),
2019 fruit::ActiveModel {
2020 id: Set(2),
2021 name: Set("Unnamed".to_owned()),
2022 cake_id: Set(None),
2023 }
2024 );
2025 }
2026
2027 #[test]
2028 #[cfg(feature = "macros")]
2029 fn test_derive_try_into_model_1() {
2030 mod my_fruit {
2031 use crate as sea_orm;
2032 use crate::entity::prelude::*;
2033
2034 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2035 #[sea_orm(table_name = "fruit")]
2036 pub struct Model {
2037 #[sea_orm(primary_key)]
2038 pub id: i32,
2039 pub name: String,
2040 pub cake_id: Option<i32>,
2041 }
2042
2043 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2044 pub enum Relation {}
2045
2046 impl ActiveModelBehavior for ActiveModel {}
2047 }
2048 assert_eq!(
2049 my_fruit::ActiveModel {
2050 id: Set(1),
2051 name: Set("Pineapple".to_owned()),
2052 cake_id: Set(None),
2053 }
2054 .try_into_model()
2055 .unwrap(),
2056 my_fruit::Model {
2057 id: 1,
2058 name: "Pineapple".to_owned(),
2059 cake_id: None,
2060 }
2061 );
2062
2063 assert_eq!(
2064 my_fruit::ActiveModel {
2065 id: Set(2),
2066 name: Set("Apple".to_owned()),
2067 cake_id: Set(Some(1)),
2068 }
2069 .try_into_model()
2070 .unwrap(),
2071 my_fruit::Model {
2072 id: 2,
2073 name: "Apple".to_owned(),
2074 cake_id: Some(1),
2075 }
2076 );
2077
2078 assert_eq!(
2079 my_fruit::ActiveModel {
2080 id: Set(1),
2081 name: NotSet,
2082 cake_id: Set(None),
2083 }
2084 .try_into_model(),
2085 Err(DbErr::AttrNotSet(String::from("name")))
2086 );
2087
2088 assert_eq!(
2089 my_fruit::ActiveModel {
2090 id: Set(1),
2091 name: Set("Pineapple".to_owned()),
2092 cake_id: NotSet,
2093 }
2094 .try_into_model(),
2095 Err(DbErr::AttrNotSet(String::from("cake_id")))
2096 );
2097 }
2098
2099 #[test]
2100 #[cfg(feature = "macros")]
2101 fn test_derive_try_into_model_2() {
2102 mod my_fruit {
2103 use crate as sea_orm;
2104 use crate::entity::prelude::*;
2105
2106 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2107 #[sea_orm(table_name = "fruit")]
2108 pub struct Model {
2109 #[sea_orm(primary_key)]
2110 pub id: i32,
2111 pub name: String,
2112 #[sea_orm(ignore)]
2113 pub cake_id: Option<i32>,
2114 }
2115
2116 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2117 pub enum Relation {}
2118
2119 impl ActiveModelBehavior for ActiveModel {}
2120 }
2121 assert_eq!(
2122 my_fruit::ActiveModel {
2123 id: Set(1),
2124 name: Set("Pineapple".to_owned()),
2125 }
2126 .try_into_model()
2127 .unwrap(),
2128 my_fruit::Model {
2129 id: 1,
2130 name: "Pineapple".to_owned(),
2131 cake_id: None,
2132 }
2133 );
2134 }
2135
2136 #[test]
2137 #[cfg(feature = "macros")]
2138 fn test_derive_try_into_model_3() {
2139 mod my_fruit {
2140 use crate as sea_orm;
2141 use crate::entity::prelude::*;
2142
2143 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2144 #[sea_orm(table_name = "fruit")]
2145 pub struct Model {
2146 #[sea_orm(primary_key)]
2147 pub id: i32,
2148 #[sea_orm(ignore)]
2149 pub name: String,
2150 pub cake_id: Option<i32>,
2151 }
2152
2153 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2154 pub enum Relation {}
2155
2156 impl ActiveModelBehavior for ActiveModel {}
2157 }
2158 assert_eq!(
2159 my_fruit::ActiveModel {
2160 id: Set(1),
2161 cake_id: Set(Some(1)),
2162 }
2163 .try_into_model()
2164 .unwrap(),
2165 my_fruit::Model {
2166 id: 1,
2167 name: "".to_owned(),
2168 cake_id: Some(1),
2169 }
2170 );
2171 }
2172
2173 #[test]
2174 #[cfg(feature = "with-json")]
2175 fn test_active_model_set_from_json_1() {
2176 assert_eq!(
2177 cake::ActiveModel::from_json(json!({
2178 "id": 1,
2179 "name": "Apple Pie",
2180 }))
2181 .unwrap(),
2182 cake::ActiveModel {
2183 id: Set(1),
2184 name: Set("Apple Pie".to_owned()),
2185 }
2186 );
2187
2188 assert_eq!(
2189 cake::ActiveModel::from_json(json!({
2190 "id": 1,
2191 }))
2192 .unwrap(),
2193 cake::ActiveModel {
2194 id: Set(1),
2195 name: NotSet,
2196 }
2197 );
2198
2199 assert_eq!(
2200 cake::ActiveModel::from_json(json!({
2201 "name": "Apple Pie",
2202 }))
2203 .unwrap(),
2204 cake::ActiveModel {
2205 id: NotSet,
2206 name: Set("Apple Pie".to_owned()),
2207 }
2208 );
2209
2210 let mut cake: cake::ActiveModel = Default::default();
2211 cake.set_from_json(json!({
2212 "name": "Apple Pie",
2213 }))
2214 .unwrap();
2215 assert_eq!(
2216 cake,
2217 cake::ActiveModel {
2218 id: NotSet,
2219 name: Set("Apple Pie".to_owned()),
2220 }
2221 );
2222 }
2223
2224 #[test]
2225 #[cfg(feature = "with-json")]
2226 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
2227 let mut fruit: fruit::ActiveModel = Default::default();
2228
2229 fruit.set_from_json(json!({
2230 "name": "Apple",
2231 }))?;
2232 assert_eq!(
2233 fruit,
2234 fruit::ActiveModel {
2235 id: ActiveValue::NotSet,
2236 name: ActiveValue::Set("Apple".to_owned()),
2237 cake_id: ActiveValue::NotSet,
2238 }
2239 );
2240
2241 assert_eq!(
2242 fruit::ActiveModel::from_json(json!({
2243 "name": "Apple",
2244 }))?,
2245 fruit::ActiveModel {
2246 id: ActiveValue::NotSet,
2247 name: ActiveValue::Set("Apple".to_owned()),
2248 cake_id: ActiveValue::NotSet,
2249 }
2250 );
2251
2252 fruit.set_from_json(json!({
2253 "name": "Apple",
2254 "cake_id": null,
2255 }))?;
2256 assert_eq!(
2257 fruit,
2258 fruit::ActiveModel {
2259 id: ActiveValue::NotSet,
2260 name: ActiveValue::Set("Apple".to_owned()),
2261 cake_id: ActiveValue::Set(None),
2262 }
2263 );
2264
2265 fruit.set_from_json(json!({
2266 "id": null,
2267 "name": "Apple",
2268 "cake_id": 1,
2269 }))?;
2270 assert_eq!(
2271 fruit,
2272 fruit::ActiveModel {
2273 id: ActiveValue::NotSet,
2274 name: ActiveValue::Set("Apple".to_owned()),
2275 cake_id: ActiveValue::Set(Some(1)),
2276 }
2277 );
2278
2279 fruit.set_from_json(json!({
2280 "id": 2,
2281 "name": "Apple",
2282 "cake_id": 1,
2283 }))?;
2284 assert_eq!(
2285 fruit,
2286 fruit::ActiveModel {
2287 id: ActiveValue::NotSet,
2288 name: ActiveValue::Set("Apple".to_owned()),
2289 cake_id: ActiveValue::Set(Some(1)),
2290 }
2291 );
2292
2293 let mut fruit = fruit::ActiveModel {
2294 id: ActiveValue::Set(1),
2295 name: ActiveValue::NotSet,
2296 cake_id: ActiveValue::NotSet,
2297 };
2298 fruit.set_from_json(json!({
2299 "id": 8,
2300 "name": "Apple",
2301 "cake_id": 1,
2302 }))?;
2303 assert_eq!(
2304 fruit,
2305 fruit::ActiveModel {
2306 id: ActiveValue::Set(1),
2307 name: ActiveValue::Set("Apple".to_owned()),
2308 cake_id: ActiveValue::Set(Some(1)),
2309 }
2310 );
2311
2312 Ok(())
2313 }
2314
2315 #[smol_potat::test]
2316 #[cfg(feature = "with-json")]
2317 async fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
2318 use crate::*;
2319
2320 let db = MockDatabase::new(DbBackend::Postgres)
2321 .append_exec_results([
2322 MockExecResult {
2323 last_insert_id: 1,
2324 rows_affected: 1,
2325 },
2326 MockExecResult {
2327 last_insert_id: 1,
2328 rows_affected: 1,
2329 },
2330 ])
2331 .append_query_results([
2332 [fruit::Model {
2333 id: 1,
2334 name: "Apple".to_owned(),
2335 cake_id: None,
2336 }],
2337 [fruit::Model {
2338 id: 2,
2339 name: "Orange".to_owned(),
2340 cake_id: Some(1),
2341 }],
2342 ])
2343 .into_connection();
2344
2345 let mut fruit: fruit::ActiveModel = Default::default();
2346 fruit.set_from_json(json!({
2347 "name": "Apple",
2348 }))?;
2349 fruit.save(&db).await?;
2350
2351 let mut fruit = fruit::ActiveModel {
2352 id: Set(2),
2353 ..Default::default()
2354 };
2355 fruit.set_from_json(json!({
2356 "id": 9,
2357 "name": "Orange",
2358 "cake_id": 1,
2359 }))?;
2360 fruit.save(&db).await?;
2361
2362 assert_eq!(
2363 db.into_transaction_log(),
2364 [
2365 Transaction::from_sql_and_values(
2366 DbBackend::Postgres,
2367 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
2368 ["Apple".into()],
2369 ),
2370 Transaction::from_sql_and_values(
2371 DbBackend::Postgres,
2372 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2373 ["Orange".into(), 1i32.into(), 2i32.into()],
2374 ),
2375 ]
2376 );
2377
2378 Ok(())
2379 }
2380
2381 #[test]
2382 fn test_active_model_is_changed() {
2383 let mut fruit: fruit::ActiveModel = Default::default();
2384 assert!(!fruit.is_changed());
2385
2386 fruit.set(fruit::Column::Name, "apple".into());
2387 assert!(fruit.is_changed());
2388
2389 let mut fruit = fruit::Model {
2390 id: 1,
2391 name: "".into(),
2392 cake_id: None,
2393 };
2394 fruit.set("name".parse().unwrap(), "orange".into());
2395 assert_eq!(fruit.name, "orange");
2396 }
2397
2398 #[test]
2399 fn test_reset_1() {
2400 assert_eq!(
2401 fruit::Model {
2402 id: 1,
2403 name: "Apple".into(),
2404 cake_id: None,
2405 }
2406 .into_active_model(),
2407 fruit::ActiveModel {
2408 id: Unchanged(1),
2409 name: Unchanged("Apple".into()),
2410 cake_id: Unchanged(None)
2411 },
2412 );
2413
2414 assert_eq!(
2415 fruit::Model {
2416 id: 1,
2417 name: "Apple".into(),
2418 cake_id: None,
2419 }
2420 .into_active_model()
2421 .reset_all(),
2422 fruit::ActiveModel {
2423 id: Set(1),
2424 name: Set("Apple".into()),
2425 cake_id: Set(None)
2426 },
2427 );
2428
2429 assert_eq!(
2430 fruit::Model {
2431 id: 1,
2432 name: "Apple".into(),
2433 cake_id: Some(2),
2434 }
2435 .into_active_model(),
2436 fruit::ActiveModel {
2437 id: Unchanged(1),
2438 name: Unchanged("Apple".into()),
2439 cake_id: Unchanged(Some(2)),
2440 },
2441 );
2442
2443 assert_eq!(
2444 fruit::Model {
2445 id: 1,
2446 name: "Apple".into(),
2447 cake_id: Some(2),
2448 }
2449 .into_active_model()
2450 .reset_all(),
2451 fruit::ActiveModel {
2452 id: Set(1),
2453 name: Set("Apple".into()),
2454 cake_id: Set(Some(2)),
2455 },
2456 );
2457 }
2458
2459 #[smol_potat::test]
2460 async fn test_reset_2() -> Result<(), DbErr> {
2461 use crate::*;
2462
2463 let db = MockDatabase::new(DbBackend::Postgres)
2464 .append_exec_results(vec![
2465 MockExecResult {
2466 last_insert_id: 1,
2467 rows_affected: 1,
2468 },
2469 MockExecResult {
2470 last_insert_id: 1,
2471 rows_affected: 1,
2472 },
2473 ])
2474 .append_query_results(vec![
2475 vec![fruit::Model {
2476 id: 1,
2477 name: "Apple".to_owned(),
2478 cake_id: None,
2479 }],
2480 vec![fruit::Model {
2481 id: 1,
2482 name: "Apple".to_owned(),
2483 cake_id: None,
2484 }],
2485 ])
2486 .into_connection();
2487
2488 fruit::Model {
2489 id: 1,
2490 name: "Apple".into(),
2491 cake_id: None,
2492 }
2493 .into_active_model()
2494 .update(&db)
2495 .await?;
2496
2497 fruit::Model {
2498 id: 1,
2499 name: "Apple".into(),
2500 cake_id: None,
2501 }
2502 .into_active_model()
2503 .reset_all()
2504 .update(&db)
2505 .await?;
2506
2507 assert_eq!(
2508 db.into_transaction_log(),
2509 vec![
2510 Transaction::from_sql_and_values(
2511 DbBackend::Postgres,
2512 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
2513 vec![1i32.into(), 1u64.into()],
2514 ),
2515 Transaction::from_sql_and_values(
2516 DbBackend::Postgres,
2517 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2518 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
2519 ),
2520 ]
2521 );
2522
2523 Ok(())
2524 }
2525
2526 #[test]
2527 fn test_active_model_default_values() {
2528 assert_eq!(
2529 fruit::ActiveModel::default_values(),
2530 fruit::ActiveModel {
2531 id: Set(0),
2532 name: Set("".into()),
2533 cake_id: Set(None),
2534 },
2535 );
2536
2537 assert_eq!(
2538 lunch_set::ActiveModel::default_values(),
2539 lunch_set::ActiveModel {
2540 id: Set(0),
2541 name: Set("".into()),
2542 tea: NotSet,
2543 },
2544 );
2545 }
2546
2547 #[test]
2548 fn test_active_model_set_parent_key() {
2549 let mut fruit = fruit::Model {
2550 id: 2,
2551 name: "F".into(),
2552 cake_id: None,
2553 }
2554 .into_active_model();
2555
2556 let cake = cake::Model {
2557 id: 4,
2558 name: "C".into(),
2559 }
2560 .into_active_model();
2561
2562 fruit.set_parent_key(&cake).unwrap();
2563
2564 assert_eq!(
2565 fruit,
2566 fruit::ActiveModel {
2567 id: Unchanged(2),
2568 name: Unchanged("F".into()),
2569 cake_id: Set(Some(4)),
2570 }
2571 );
2572
2573 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
2574
2575 assert_eq!(
2576 fruit,
2577 fruit::ActiveModel {
2578 id: Unchanged(2),
2579 name: Unchanged("F".into()),
2580 cake_id: Set(None),
2581 }
2582 );
2583
2584 let mut cake_filling = cake_filling::ActiveModel::new();
2585
2586 cake_filling.set_parent_key(&cake).unwrap();
2587
2588 assert_eq!(
2589 cake_filling,
2590 cake_filling::ActiveModel {
2591 cake_id: Set(4),
2592 filling_id: NotSet,
2593 }
2594 );
2595 }
2596}