1use super::{ActiveValue, ActiveValue::*};
2use crate::{
3 ColumnTrait, Condition, ConnectionTrait, DbBackend, DeleteResult, EntityName, EntityTrait,
4 IdenStatic, Iterable, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter,
5 Related, RelatedSelfVia, RelationDef, RelationTrait, Value,
6 error::*,
7 query::{
8 clear_key_on_active_model, column_tuple_in_condition, get_key_from_active_model,
9 set_key_on_active_model,
10 },
11};
12use sea_query::ValueTuple;
13use std::fmt::Debug;
14
15#[async_trait::async_trait]
27pub trait ActiveModelTrait: Clone + Debug {
28 type Entity: EntityTrait;
30
31 fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
33
34 fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
36
37 fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
39 self.try_set(c, v)
40 .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
41 }
42
43 fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
45
46 fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
48
49 fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
51
52 fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
54
55 fn default() -> Self;
57
58 fn default_values() -> Self;
60
61 fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
64
65 fn reset_all(mut self) -> Self {
68 for col in <Self::Entity as EntityTrait>::Column::iter() {
69 self.reset(col);
70 }
71 self
72 }
73
74 fn get_primary_key_value(&self) -> Option<ValueTuple> {
76 let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
77 macro_rules! next {
78 () => {
79 self.get(cols.next()?.into_column()).into_value()?
80 };
81 }
82 match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
83 1 => {
84 let s1 = next!();
85 Some(ValueTuple::One(s1))
86 }
87 2 => {
88 let s1 = next!();
89 let s2 = next!();
90 Some(ValueTuple::Two(s1, s2))
91 }
92 3 => {
93 let s1 = next!();
94 let s2 = next!();
95 let s3 = next!();
96 Some(ValueTuple::Three(s1, s2, s3))
97 }
98 len => {
99 let mut vec = Vec::with_capacity(len);
100 for _ in 0..len {
101 let s = next!();
102 vec.push(s);
103 }
104 Some(ValueTuple::Many(vec))
105 }
106 }
107 }
108
109 async fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
216 where
217 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
218 Self: ActiveModelBehavior,
219 C: ConnectionTrait,
220 {
221 let am = ActiveModelBehavior::before_save(self, db, true).await?;
222 let model = <Self::Entity as EntityTrait>::insert(am)
223 .exec_with_returning(db)
224 .await?;
225 Self::after_save(model, db, true).await
226 }
227
228 async fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
338 where
339 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
340 Self: ActiveModelBehavior,
341 C: ConnectionTrait,
342 {
343 let am = ActiveModelBehavior::before_save(self, db, false).await?;
344 let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db).await?;
345 Self::after_save(model, db, false).await
346 }
347
348 async fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
351 where
352 <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
353 Self: ActiveModelBehavior,
354 C: ConnectionTrait,
355 {
356 let res = if !self.is_update() {
357 self.insert(db).await
358 } else {
359 self.update(db).await
360 }?;
361 Ok(res.into_active_model())
362 }
363
364 #[doc(hidden)]
366 fn is_update(&self) -> bool {
367 let mut is_update = true;
368 for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
369 let col = key.into_column();
370 if self.is_not_set(col) {
371 is_update = false;
372 break;
373 }
374 }
375 is_update
376 }
377
378 async fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
422 where
423 Self: ActiveModelBehavior,
424 C: ConnectionTrait,
425 {
426 let am = ActiveModelBehavior::before_delete(self, db).await?;
427 let am_clone = am.clone();
428 let delete_res = Self::Entity::delete(am).exec(db).await?;
429 ActiveModelBehavior::after_delete(am_clone, db).await?;
430 Ok(delete_res)
431 }
432
433 #[cfg(feature = "with-json")]
437 fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
438 where
439 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
440 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
441 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
442 serde::de::Deserialize<'de> + serde::Serialize,
443 {
444 use crate::Iterable;
445
446 let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
448 <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
449 .map(|pk| (pk.into_column(), self.take(pk.into_column())))
450 .collect();
451
452 *self = Self::from_json(json)?;
454
455 for (col, active_value) in primary_key_values {
457 match active_value {
458 ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
459 NotSet => self.not_set(col),
460 }
461 }
462
463 Ok(())
464 }
465
466 #[cfg(feature = "with-json")]
468 fn from_json(mut json: serde_json::Value) -> Result<Self, DbErr>
469 where
470 Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
471 <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
472 for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
473 serde::de::Deserialize<'de> + serde::Serialize,
474 {
475 use crate::{IdenStatic, Iterable};
476
477 let serde_json::Value::Object(obj) = &json else {
478 return Err(DbErr::Json(format!(
479 "invalid type: expected JSON object for {}",
480 <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
481 )));
482 };
483
484 let mut json_keys: Vec<(<Self::Entity as EntityTrait>::Column, bool)> = Vec::new();
486
487 for col in <<Self::Entity as EntityTrait>::Column>::iter() {
488 let key = col.json_key();
489 let has_key = obj.contains_key(key);
490 json_keys.push((col, has_key));
491 }
492
493 let dummy_model = Self::default_values();
495 if let Ok(dummy_model) = dummy_model.try_into_model() {
496 if let Ok(mut dummy_json) = serde_json::to_value(&dummy_model) {
497 let serde_json::Value::Object(merged) = &mut dummy_json else {
498 unreachable!();
499 };
500 let serde_json::Value::Object(obj) = json else {
501 unreachable!();
502 };
503 for (key, value) in obj {
505 merged.insert(key, value);
506 }
507 json = dummy_json;
508 }
509 }
510
511 let model: <Self::Entity as EntityTrait>::Model =
513 serde_json::from_value(json).map_err(json_err)?;
514 let mut am = model.into_active_model();
515
516 for (col, json_key_exists) in json_keys {
518 match (json_key_exists, am.get(col)) {
519 (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
520 am.set(col, value);
521 }
522 _ => {
523 am.not_set(col);
524 }
525 }
526 }
527
528 Ok(am)
529 }
530
531 fn is_changed(&self) -> bool {
533 <Self::Entity as EntityTrait>::Column::iter()
534 .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
535 }
536
537 #[doc(hidden)]
538 fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
540 where
541 R: EntityTrait,
542 AM: ActiveModelTrait<Entity = R>,
543 Self::Entity: Related<R>,
544 {
545 let rel_def = Self::Entity::to();
546
547 if rel_def.is_owner {
548 return Err(DbErr::Type(format!(
549 "Relation from {} to {} is not belongs_to",
550 <Self::Entity as Default>::default().as_str(),
551 <R as Default>::default().as_str()
552 )));
553 }
554
555 let values = get_key_from_active_model(&rel_def.to_col, model)?;
556
557 set_key_on_active_model(&rel_def.from_col, self, values)?;
558
559 Ok(())
560 }
561
562 #[doc(hidden)]
563 fn set_parent_key_for<R, AM>(
564 &mut self,
565 model: &AM,
566 rel: <Self::Entity as EntityTrait>::Relation,
567 ) -> Result<(), DbErr>
568 where
569 R: EntityTrait,
570 AM: ActiveModelTrait<Entity = R>,
571 {
572 let rel_def = rel.def();
573
574 if rel_def.is_owner {
575 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
576 }
577
578 let values = get_key_from_active_model(&rel_def.to_col, model)?;
579
580 set_key_on_active_model(&rel_def.from_col, self, values)?;
581
582 Ok(())
583 }
584
585 #[doc(hidden)]
586 fn set_parent_key_for_def<R, AM>(
587 &mut self,
588 model: &AM,
589 rel_def: &RelationDef,
590 ) -> Result<(), DbErr>
591 where
592 R: EntityTrait,
593 AM: ActiveModelTrait<Entity = R>,
594 {
595 if rel_def.is_owner {
596 return Err(DbErr::Type(format!(
597 "Relation {rel_def:?} is not belongs_to"
598 )));
599 }
600
601 let values = get_key_from_active_model(&rel_def.to_col, model)?;
602
603 set_key_on_active_model(&rel_def.from_col, self, values)?;
604
605 Ok(())
606 }
607
608 #[doc(hidden)]
609 fn set_parent_key_for_self_rev<AM>(
610 &mut self,
611 model: &AM,
612 rel: <Self::Entity as EntityTrait>::Relation,
613 ) -> Result<(), DbErr>
614 where
615 AM: ActiveModelTrait<Entity = Self::Entity>,
616 {
617 let rel_def = rel.def();
618
619 if !rel_def.is_owner {
620 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
621 }
622
623 let values = get_key_from_active_model(&rel_def.from_col, model)?;
624
625 set_key_on_active_model(&rel_def.to_col, self, values)?;
626
627 Ok(())
628 }
629
630 #[doc(hidden)]
631 fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
633 where
634 R: EntityTrait,
635 Self::Entity: Related<R>,
636 {
637 let rel_def = Self::Entity::to();
638
639 if rel_def.is_owner {
640 return Err(DbErr::Type(format!(
641 "Relation from {} to {} is not belongs_to",
642 <Self::Entity as Default>::default().as_str(),
643 <R as Default>::default().as_str()
644 )));
645 }
646
647 clear_key_on_active_model(&rel_def.from_col, self)
648 }
649
650 #[doc(hidden)]
651 fn clear_parent_key_for_self_rev(
652 &mut self,
653 rel: <Self::Entity as EntityTrait>::Relation,
654 ) -> Result<bool, DbErr> {
655 let rel_def = rel.def();
656
657 if !rel_def.is_owner {
658 return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
659 }
660
661 clear_key_on_active_model(&rel_def.to_col, self)
662 }
663
664 #[doc(hidden)]
665 fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
667 where
668 R: EntityTrait,
669 Self::Entity: Related<R>,
670 {
671 let rel_def = Self::Entity::to();
672
673 if rel_def.is_owner {
674 return Err(DbErr::Type(format!(
675 "Relation from {} to {} is not belongs_to",
676 <Self::Entity as Default>::default().as_str(),
677 <R as Default>::default().as_str()
678 )));
679 }
680
681 get_key_from_active_model(&rel_def.from_col, self)
682 }
683
684 #[doc(hidden)]
685 fn get_parent_key_for(
687 &self,
688 rel: <Self::Entity as EntityTrait>::Relation,
689 ) -> Result<ValueTuple, DbErr> {
690 let rel_def = rel.def();
691
692 if rel_def.is_owner {
693 return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
694 }
695
696 get_key_from_active_model(&rel_def.from_col, self)
697 }
698
699 #[doc(hidden)]
700 fn find_belongs_to_self(
701 &self,
702 rel: <Self::Entity as EntityTrait>::Relation,
703 ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
704 let rel_def = rel.def();
705
706 if !rel_def.is_owner {
707 return Err(DbErr::Type(format!(
708 "Relation {rel:?} is not has_one / has_many"
709 )));
710 }
711
712 let id = get_key_from_active_model(&rel_def.from_col, self)?;
713
714 Ok(Self::Entity::find().filter(
715 column_tuple_in_condition(
716 &<Self::Entity as Default>::default().table_ref(),
717 &rel_def.to_col,
718 &[id],
719 DbBackend::Sqlite,
720 )
721 .expect(""),
722 ))
723 }
724
725 #[doc(hidden)]
726 fn find_belongs_to_model<AM>(
727 rel_def: &RelationDef,
728 belongs_to: &AM,
729 ) -> Result<crate::query::Select<Self::Entity>, DbErr>
730 where
731 AM: ActiveModelTrait,
732 {
733 if rel_def.is_owner {
734 return Err(DbErr::Type(format!(
735 "Relation {rel_def:?} is not belongs_to"
736 )));
737 }
738
739 let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
740 Ok(<Self::Entity as EntityTrait>::find().filter(
741 column_tuple_in_condition(
742 &rel_def.from_tbl,
743 &rel_def.from_col,
744 &[id],
745 DbBackend::Sqlite,
746 )
747 .expect(""),
748 ))
749 }
750
751 fn find_related<R>(&self, _: R) -> crate::query::Select<R>
753 where
754 R: EntityTrait,
755 Self::Entity: Related<R>,
756 {
757 Self::Entity::find_related().belongs_to_active_model(self)
758 }
759
760 #[doc(hidden)]
761 fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
762 where
763 AM: ActiveModelTrait,
764 Self::Entity: Related<AM::Entity>,
765 {
766 self.find_related(AM::Entity::default())
767 }
768
769 #[doc(hidden)]
772 async fn establish_links<J, R, RM, C>(
773 &self,
774 _: J,
775 related_models: &[RM],
776 delete_leftover: bool,
777 db: &C,
778 ) -> Result<(), DbErr>
779 where
780 R: EntityTrait,
781 RM: ActiveModelTrait<Entity = R> + Sync,
782 J: EntityTrait + Related<R> + Related<Self::Entity>,
783 J::Model: IntoActiveModel<J::ActiveModel>,
784 J::ActiveModel: ActiveModelBehavior + Send,
785 C: ConnectionTrait,
786 {
787 let left = <J as Related<Self::Entity>>::to();
788 let right = <J as Related<R>>::to();
789
790 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
791 }
792
793 #[doc(hidden)]
794 async fn establish_links_self<J, RM, C>(
795 &self,
796 _: J,
797 related_models: &[RM],
798 delete_leftover: bool,
799 db: &C,
800 ) -> Result<(), DbErr>
801 where
802 RM: ActiveModelTrait<Entity = Self::Entity> + Sync,
803 J: EntityTrait,
804 J::Model: IntoActiveModel<J::ActiveModel>,
805 J::ActiveModel: ActiveModelBehavior + Send,
806 C: ConnectionTrait,
807 Self::Entity: RelatedSelfVia<J>,
808 {
809 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
810 let right = <Self::Entity as RelatedSelfVia<J>>::to();
811
812 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
813 }
814
815 #[doc(hidden)]
816 async fn establish_links_self_rev<J, RM, C>(
817 &self,
818 _: J,
819 related_models: &[RM],
820 delete_leftover: bool,
821 db: &C,
822 ) -> Result<(), DbErr>
823 where
824 RM: ActiveModelTrait<Entity = Self::Entity> + Sync,
825 J: EntityTrait,
826 J::Model: IntoActiveModel<J::ActiveModel>,
827 J::ActiveModel: ActiveModelBehavior + Send,
828 C: ConnectionTrait,
829 Self::Entity: RelatedSelfVia<J>,
830 {
831 let left = <Self::Entity as RelatedSelfVia<J>>::to();
832 let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
833
834 establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db).await
835 }
836
837 #[doc(hidden)]
838 async fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
839 where
840 J: EntityTrait + Related<Self::Entity>,
841 C: ConnectionTrait,
842 {
843 let rel_def = <J as Related<Self::Entity>>::to();
844 let id = get_key_from_active_model(&rel_def.to_col, self)?;
845
846 J::delete_many()
847 .filter(
848 column_tuple_in_condition(
849 &rel_def.from_tbl,
850 &rel_def.from_col,
851 &[id],
852 DbBackend::Sqlite,
853 )
854 .expect(""),
855 )
856 .exec(db)
857 .await
858 }
859
860 #[doc(hidden)]
861 async fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
862 where
863 J: EntityTrait,
864 C: ConnectionTrait,
865 Self::Entity: RelatedSelfVia<J>,
866 {
867 let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
868 let right = <Self::Entity as RelatedSelfVia<J>>::to();
869
870 let id = get_key_from_active_model(&left.to_col, self)?;
871
872 if left.to_col != right.to_col {
873 return Err(DbErr::Type("Expect Self Referencing Relation".into()));
874 }
875
876 J::delete_many()
877 .filter(
878 Condition::any()
879 .add(
880 column_tuple_in_condition(
881 &left.from_tbl,
882 &left.from_col,
883 std::slice::from_ref(&id),
884 DbBackend::Sqlite,
885 )
886 .expect(""),
887 )
888 .add(
889 column_tuple_in_condition(
890 &right.from_tbl,
891 &right.from_col,
892 std::slice::from_ref(&id),
893 DbBackend::Sqlite,
894 )
895 .expect(""),
896 ),
897 )
898 .exec(db)
899 .await
900 }
901}
902
903#[allow(unused_variables)]
931#[async_trait::async_trait]
932pub trait ActiveModelBehavior: ActiveModelTrait {
933 fn new() -> Self {
946 <Self as ActiveModelTrait>::default()
947 }
948
949 async fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
951 where
952 C: ConnectionTrait,
953 {
954 Ok(self)
955 }
956
957 async fn after_save<C>(
959 model: <Self::Entity as EntityTrait>::Model,
960 db: &C,
961 insert: bool,
962 ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
963 where
964 C: ConnectionTrait,
965 {
966 Ok(model)
967 }
968
969 async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
971 where
972 C: ConnectionTrait,
973 {
974 Ok(self)
975 }
976
977 async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
979 where
980 C: ConnectionTrait,
981 {
982 Ok(self)
983 }
984}
985
986pub trait IntoActiveModel<A>
988where
989 A: ActiveModelTrait,
990{
991 fn into_active_model(self) -> A;
993}
994
995impl<A> IntoActiveModel<A> for A
996where
997 A: ActiveModelTrait,
998{
999 fn into_active_model(self) -> A {
1000 self
1001 }
1002}
1003
1004async fn establish_links<EM, J, RM, C>(
1005 model: &EM,
1006 related_models: &[RM],
1007 left: RelationDef,
1008 right: RelationDef,
1009 delete_leftover: bool,
1010 db: &C,
1011) -> Result<(), DbErr>
1012where
1013 EM: ActiveModelTrait,
1014 RM: ActiveModelTrait,
1015 J: EntityTrait,
1016 J::Model: IntoActiveModel<J::ActiveModel>,
1017 J::ActiveModel: ActiveModelBehavior,
1018 C: ConnectionTrait,
1019{
1020 let mut require_leftover = true;
1021
1022 if related_models.is_empty() {
1023 require_leftover = false;
1025 }
1026
1027 let primary_key = J::primary_key_identity();
1028 if require_leftover
1029 && primary_key.fully_contains(&left.from_col)
1030 && primary_key.fully_contains(&right.from_col)
1031 {
1032 require_leftover = false;
1035 }
1036
1037 let mut leftover = Vec::new();
1038 if delete_leftover || require_leftover {
1039 for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(&left, model)?
1040 .all(db)
1041 .await?
1042 {
1043 let item = item.into_active_model();
1044 let key = get_key_from_active_model(&right.from_col, &item)?;
1045 leftover.push((item, key));
1046 }
1047 }
1048 let leftover = leftover; let mut via_models = Vec::new();
1051 let mut all_keys = std::collections::HashSet::new();
1052
1053 for related_model in related_models {
1054 let mut via: J::ActiveModel = ActiveModelBehavior::new();
1055 via.set_parent_key_for_def(model, &left)?;
1056 via.set_parent_key_for_def(related_model, &right)?;
1057 let via_key = get_key_from_active_model(&right.from_col, &via)?;
1058 if !leftover.iter().any(|t| t.1 == via_key) {
1059 via_models.push(via);
1061 }
1062 if delete_leftover {
1063 all_keys.insert(via_key);
1064 }
1065 }
1066
1067 if delete_leftover {
1068 let mut to_delete = Vec::new();
1069 for (leftover, key) in leftover {
1070 if !all_keys.contains(&key) {
1071 to_delete.push(
1072 leftover
1073 .get_primary_key_value()
1074 .expect("item is a full model"),
1075 );
1076 }
1077 }
1078 if !to_delete.is_empty() {
1079 J::delete_many()
1080 .filter_by_value_tuples(&to_delete)
1081 .exec(db)
1082 .await?;
1083 }
1084 }
1085
1086 if !via_models.is_empty() {
1087 J::insert_many(via_models)
1089 .on_conflict_do_nothing()
1090 .exec(db)
1091 .await?;
1092 }
1093
1094 Ok(())
1095}
1096
1097#[cfg(test)]
1098mod tests {
1099 use crate::{DbErr, entity::*, tests_cfg::*};
1100 use pretty_assertions::assert_eq;
1101
1102 #[cfg(feature = "with-json")]
1103 use serde_json::json;
1104
1105 #[test]
1106 #[cfg(feature = "macros")]
1107 fn test_derive_into_active_model_1() {
1108 mod my_fruit {
1109 pub use super::fruit::*;
1110 use crate as sea_orm;
1111 use crate::entity::prelude::*;
1112
1113 #[derive(DeriveIntoActiveModel)]
1114 pub struct NewFruit {
1115 pub name: String,
1117 pub cake_id: i32,
1119 }
1120 }
1121
1122 assert_eq!(
1123 my_fruit::NewFruit {
1124 name: "Apple".to_owned(),
1125 cake_id: 1,
1126 }
1127 .into_active_model(),
1128 fruit::ActiveModel {
1129 id: NotSet,
1130 name: Set("Apple".to_owned()),
1131 cake_id: Set(Some(1)),
1132 }
1133 );
1134 }
1135
1136 #[test]
1137 #[cfg(feature = "macros")]
1138 fn test_derive_into_active_model_2() {
1139 use crate as sea_orm;
1140 use crate::entity::prelude::*;
1141
1142 #[derive(DeriveIntoActiveModel)]
1143 #[sea_orm(active_model = "fruit::ActiveModel")]
1144 struct FruitName {
1145 name: String,
1146 }
1147
1148 assert_eq!(
1149 FruitName {
1150 name: "Apple Pie".to_owned(),
1151 }
1152 .into_active_model(),
1153 fruit::ActiveModel {
1154 id: NotSet,
1155 name: Set("Apple Pie".to_owned()),
1156 cake_id: NotSet,
1157 }
1158 );
1159
1160 #[derive(DeriveIntoActiveModel)]
1161 #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1162 struct FruitCake {
1163 cake_id: Option<Option<i32>>,
1164 }
1165
1166 assert_eq!(
1167 FruitCake {
1168 cake_id: Some(Some(1)),
1169 }
1170 .into_active_model(),
1171 fruit::ActiveModel {
1172 id: NotSet,
1173 name: NotSet,
1174 cake_id: Set(Some(1)),
1175 }
1176 );
1177
1178 assert_eq!(
1179 FruitCake {
1180 cake_id: Some(None),
1181 }
1182 .into_active_model(),
1183 fruit::ActiveModel {
1184 id: NotSet,
1185 name: NotSet,
1186 cake_id: Set(None),
1187 }
1188 );
1189
1190 assert_eq!(
1191 FruitCake { cake_id: None }.into_active_model(),
1192 fruit::ActiveModel {
1193 id: NotSet,
1194 name: NotSet,
1195 cake_id: NotSet,
1196 }
1197 );
1198 }
1199
1200 #[test]
1201 #[cfg(feature = "macros")]
1202 fn test_derive_try_into_model_1() {
1203 mod my_fruit {
1204 use crate as sea_orm;
1205 use crate::entity::prelude::*;
1206
1207 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1208 #[sea_orm(table_name = "fruit")]
1209 pub struct Model {
1210 #[sea_orm(primary_key)]
1211 pub id: i32,
1212 pub name: String,
1213 pub cake_id: Option<i32>,
1214 }
1215
1216 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1217 pub enum Relation {}
1218
1219 impl ActiveModelBehavior for ActiveModel {}
1220 }
1221 assert_eq!(
1222 my_fruit::ActiveModel {
1223 id: Set(1),
1224 name: Set("Pineapple".to_owned()),
1225 cake_id: Set(None),
1226 }
1227 .try_into_model()
1228 .unwrap(),
1229 my_fruit::Model {
1230 id: 1,
1231 name: "Pineapple".to_owned(),
1232 cake_id: None,
1233 }
1234 );
1235
1236 assert_eq!(
1237 my_fruit::ActiveModel {
1238 id: Set(2),
1239 name: Set("Apple".to_owned()),
1240 cake_id: Set(Some(1)),
1241 }
1242 .try_into_model()
1243 .unwrap(),
1244 my_fruit::Model {
1245 id: 2,
1246 name: "Apple".to_owned(),
1247 cake_id: Some(1),
1248 }
1249 );
1250
1251 assert_eq!(
1252 my_fruit::ActiveModel {
1253 id: Set(1),
1254 name: NotSet,
1255 cake_id: Set(None),
1256 }
1257 .try_into_model(),
1258 Err(DbErr::AttrNotSet(String::from("name")))
1259 );
1260
1261 assert_eq!(
1262 my_fruit::ActiveModel {
1263 id: Set(1),
1264 name: Set("Pineapple".to_owned()),
1265 cake_id: NotSet,
1266 }
1267 .try_into_model(),
1268 Err(DbErr::AttrNotSet(String::from("cake_id")))
1269 );
1270 }
1271
1272 #[test]
1273 #[cfg(feature = "macros")]
1274 fn test_derive_try_into_model_2() {
1275 mod my_fruit {
1276 use crate as sea_orm;
1277 use crate::entity::prelude::*;
1278
1279 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1280 #[sea_orm(table_name = "fruit")]
1281 pub struct Model {
1282 #[sea_orm(primary_key)]
1283 pub id: i32,
1284 pub name: String,
1285 #[sea_orm(ignore)]
1286 pub cake_id: Option<i32>,
1287 }
1288
1289 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1290 pub enum Relation {}
1291
1292 impl ActiveModelBehavior for ActiveModel {}
1293 }
1294 assert_eq!(
1295 my_fruit::ActiveModel {
1296 id: Set(1),
1297 name: Set("Pineapple".to_owned()),
1298 }
1299 .try_into_model()
1300 .unwrap(),
1301 my_fruit::Model {
1302 id: 1,
1303 name: "Pineapple".to_owned(),
1304 cake_id: None,
1305 }
1306 );
1307 }
1308
1309 #[test]
1310 #[cfg(feature = "macros")]
1311 fn test_derive_try_into_model_3() {
1312 mod my_fruit {
1313 use crate as sea_orm;
1314 use crate::entity::prelude::*;
1315
1316 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1317 #[sea_orm(table_name = "fruit")]
1318 pub struct Model {
1319 #[sea_orm(primary_key)]
1320 pub id: i32,
1321 #[sea_orm(ignore)]
1322 pub name: String,
1323 pub cake_id: Option<i32>,
1324 }
1325
1326 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1327 pub enum Relation {}
1328
1329 impl ActiveModelBehavior for ActiveModel {}
1330 }
1331 assert_eq!(
1332 my_fruit::ActiveModel {
1333 id: Set(1),
1334 cake_id: Set(Some(1)),
1335 }
1336 .try_into_model()
1337 .unwrap(),
1338 my_fruit::Model {
1339 id: 1,
1340 name: "".to_owned(),
1341 cake_id: Some(1),
1342 }
1343 );
1344 }
1345
1346 #[test]
1347 #[cfg(feature = "with-json")]
1348 fn test_active_model_set_from_json_1() {
1349 assert_eq!(
1350 cake::ActiveModel::from_json(json!({
1351 "id": 1,
1352 "name": "Apple Pie",
1353 }))
1354 .unwrap(),
1355 cake::ActiveModel {
1356 id: Set(1),
1357 name: Set("Apple Pie".to_owned()),
1358 }
1359 );
1360
1361 assert_eq!(
1362 cake::ActiveModel::from_json(json!({
1363 "id": 1,
1364 }))
1365 .unwrap(),
1366 cake::ActiveModel {
1367 id: Set(1),
1368 name: NotSet,
1369 }
1370 );
1371
1372 assert_eq!(
1373 cake::ActiveModel::from_json(json!({
1374 "name": "Apple Pie",
1375 }))
1376 .unwrap(),
1377 cake::ActiveModel {
1378 id: NotSet,
1379 name: Set("Apple Pie".to_owned()),
1380 }
1381 );
1382
1383 let mut cake: cake::ActiveModel = Default::default();
1384 cake.set_from_json(json!({
1385 "name": "Apple Pie",
1386 }))
1387 .unwrap();
1388 assert_eq!(
1389 cake,
1390 cake::ActiveModel {
1391 id: NotSet,
1392 name: Set("Apple Pie".to_owned()),
1393 }
1394 );
1395 }
1396
1397 #[test]
1398 #[cfg(feature = "with-json")]
1399 fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1400 let mut fruit: fruit::ActiveModel = Default::default();
1401
1402 fruit.set_from_json(json!({
1403 "name": "Apple",
1404 }))?;
1405 assert_eq!(
1406 fruit,
1407 fruit::ActiveModel {
1408 id: ActiveValue::NotSet,
1409 name: ActiveValue::Set("Apple".to_owned()),
1410 cake_id: ActiveValue::NotSet,
1411 }
1412 );
1413
1414 assert_eq!(
1415 fruit::ActiveModel::from_json(json!({
1416 "name": "Apple",
1417 }))?,
1418 fruit::ActiveModel {
1419 id: ActiveValue::NotSet,
1420 name: ActiveValue::Set("Apple".to_owned()),
1421 cake_id: ActiveValue::NotSet,
1422 }
1423 );
1424
1425 fruit.set_from_json(json!({
1426 "name": "Apple",
1427 "cake_id": null,
1428 }))?;
1429 assert_eq!(
1430 fruit,
1431 fruit::ActiveModel {
1432 id: ActiveValue::NotSet,
1433 name: ActiveValue::Set("Apple".to_owned()),
1434 cake_id: ActiveValue::Set(None),
1435 }
1436 );
1437
1438 fruit.set_from_json(json!({
1439 "id": null,
1440 "name": "Apple",
1441 "cake_id": 1,
1442 }))?;
1443 assert_eq!(
1444 fruit,
1445 fruit::ActiveModel {
1446 id: ActiveValue::NotSet,
1447 name: ActiveValue::Set("Apple".to_owned()),
1448 cake_id: ActiveValue::Set(Some(1)),
1449 }
1450 );
1451
1452 fruit.set_from_json(json!({
1453 "id": 2,
1454 "name": "Apple",
1455 "cake_id": 1,
1456 }))?;
1457 assert_eq!(
1458 fruit,
1459 fruit::ActiveModel {
1460 id: ActiveValue::NotSet,
1461 name: ActiveValue::Set("Apple".to_owned()),
1462 cake_id: ActiveValue::Set(Some(1)),
1463 }
1464 );
1465
1466 let mut fruit = fruit::ActiveModel {
1467 id: ActiveValue::Set(1),
1468 name: ActiveValue::NotSet,
1469 cake_id: ActiveValue::NotSet,
1470 };
1471 fruit.set_from_json(json!({
1472 "id": 8,
1473 "name": "Apple",
1474 "cake_id": 1,
1475 }))?;
1476 assert_eq!(
1477 fruit,
1478 fruit::ActiveModel {
1479 id: ActiveValue::Set(1),
1480 name: ActiveValue::Set("Apple".to_owned()),
1481 cake_id: ActiveValue::Set(Some(1)),
1482 }
1483 );
1484
1485 Ok(())
1486 }
1487
1488 #[smol_potat::test]
1489 #[cfg(feature = "with-json")]
1490 async fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1491 use crate::*;
1492
1493 let db = MockDatabase::new(DbBackend::Postgres)
1494 .append_exec_results([
1495 MockExecResult {
1496 last_insert_id: 1,
1497 rows_affected: 1,
1498 },
1499 MockExecResult {
1500 last_insert_id: 1,
1501 rows_affected: 1,
1502 },
1503 ])
1504 .append_query_results([
1505 [fruit::Model {
1506 id: 1,
1507 name: "Apple".to_owned(),
1508 cake_id: None,
1509 }],
1510 [fruit::Model {
1511 id: 2,
1512 name: "Orange".to_owned(),
1513 cake_id: Some(1),
1514 }],
1515 ])
1516 .into_connection();
1517
1518 let mut fruit: fruit::ActiveModel = Default::default();
1519 fruit.set_from_json(json!({
1520 "name": "Apple",
1521 }))?;
1522 fruit.save(&db).await?;
1523
1524 let mut fruit = fruit::ActiveModel {
1525 id: Set(2),
1526 ..Default::default()
1527 };
1528 fruit.set_from_json(json!({
1529 "id": 9,
1530 "name": "Orange",
1531 "cake_id": 1,
1532 }))?;
1533 fruit.save(&db).await?;
1534
1535 assert_eq!(
1536 db.into_transaction_log(),
1537 [
1538 Transaction::from_sql_and_values(
1539 DbBackend::Postgres,
1540 r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1541 ["Apple".into()],
1542 ),
1543 Transaction::from_sql_and_values(
1544 DbBackend::Postgres,
1545 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1546 ["Orange".into(), 1i32.into(), 2i32.into()],
1547 ),
1548 ]
1549 );
1550
1551 Ok(())
1552 }
1553
1554 #[test]
1555 fn test_active_model_is_changed() {
1556 let mut fruit: fruit::ActiveModel = Default::default();
1557 assert!(!fruit.is_changed());
1558
1559 fruit.set(fruit::Column::Name, "apple".into());
1560 assert!(fruit.is_changed());
1561
1562 let mut fruit = fruit::Model {
1563 id: 1,
1564 name: "".into(),
1565 cake_id: None,
1566 };
1567 fruit.set("name".parse().unwrap(), "orange".into());
1568 assert_eq!(fruit.name, "orange");
1569 }
1570
1571 #[test]
1572 fn test_reset_1() {
1573 assert_eq!(
1574 fruit::Model {
1575 id: 1,
1576 name: "Apple".into(),
1577 cake_id: None,
1578 }
1579 .into_active_model(),
1580 fruit::ActiveModel {
1581 id: Unchanged(1),
1582 name: Unchanged("Apple".into()),
1583 cake_id: Unchanged(None)
1584 },
1585 );
1586
1587 assert_eq!(
1588 fruit::Model {
1589 id: 1,
1590 name: "Apple".into(),
1591 cake_id: None,
1592 }
1593 .into_active_model()
1594 .reset_all(),
1595 fruit::ActiveModel {
1596 id: Set(1),
1597 name: Set("Apple".into()),
1598 cake_id: Set(None)
1599 },
1600 );
1601
1602 assert_eq!(
1603 fruit::Model {
1604 id: 1,
1605 name: "Apple".into(),
1606 cake_id: Some(2),
1607 }
1608 .into_active_model(),
1609 fruit::ActiveModel {
1610 id: Unchanged(1),
1611 name: Unchanged("Apple".into()),
1612 cake_id: Unchanged(Some(2)),
1613 },
1614 );
1615
1616 assert_eq!(
1617 fruit::Model {
1618 id: 1,
1619 name: "Apple".into(),
1620 cake_id: Some(2),
1621 }
1622 .into_active_model()
1623 .reset_all(),
1624 fruit::ActiveModel {
1625 id: Set(1),
1626 name: Set("Apple".into()),
1627 cake_id: Set(Some(2)),
1628 },
1629 );
1630 }
1631
1632 #[smol_potat::test]
1633 async fn test_reset_2() -> Result<(), DbErr> {
1634 use crate::*;
1635
1636 let db = MockDatabase::new(DbBackend::Postgres)
1637 .append_exec_results(vec![
1638 MockExecResult {
1639 last_insert_id: 1,
1640 rows_affected: 1,
1641 },
1642 MockExecResult {
1643 last_insert_id: 1,
1644 rows_affected: 1,
1645 },
1646 ])
1647 .append_query_results(vec![
1648 vec![fruit::Model {
1649 id: 1,
1650 name: "Apple".to_owned(),
1651 cake_id: None,
1652 }],
1653 vec![fruit::Model {
1654 id: 1,
1655 name: "Apple".to_owned(),
1656 cake_id: None,
1657 }],
1658 ])
1659 .into_connection();
1660
1661 fruit::Model {
1662 id: 1,
1663 name: "Apple".into(),
1664 cake_id: None,
1665 }
1666 .into_active_model()
1667 .update(&db)
1668 .await?;
1669
1670 fruit::Model {
1671 id: 1,
1672 name: "Apple".into(),
1673 cake_id: None,
1674 }
1675 .into_active_model()
1676 .reset_all()
1677 .update(&db)
1678 .await?;
1679
1680 assert_eq!(
1681 db.into_transaction_log(),
1682 vec![
1683 Transaction::from_sql_and_values(
1684 DbBackend::Postgres,
1685 r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1686 vec![1i32.into(), 1u64.into()],
1687 ),
1688 Transaction::from_sql_and_values(
1689 DbBackend::Postgres,
1690 r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1691 vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1692 ),
1693 ]
1694 );
1695
1696 Ok(())
1697 }
1698
1699 #[test]
1700 fn test_active_model_default_values() {
1701 assert_eq!(
1702 fruit::ActiveModel::default_values(),
1703 fruit::ActiveModel {
1704 id: Set(0),
1705 name: Set("".into()),
1706 cake_id: Set(None),
1707 },
1708 );
1709
1710 assert_eq!(
1711 lunch_set::ActiveModel::default_values(),
1712 lunch_set::ActiveModel {
1713 id: Set(0),
1714 name: Set("".into()),
1715 tea: NotSet,
1716 },
1717 );
1718 }
1719
1720 #[test]
1721 fn test_active_model_set_parent_key() {
1722 let mut fruit = fruit::Model {
1723 id: 2,
1724 name: "F".into(),
1725 cake_id: None,
1726 }
1727 .into_active_model();
1728
1729 let cake = cake::Model {
1730 id: 4,
1731 name: "C".into(),
1732 }
1733 .into_active_model();
1734
1735 fruit.set_parent_key(&cake).unwrap();
1736
1737 assert_eq!(
1738 fruit,
1739 fruit::ActiveModel {
1740 id: Unchanged(2),
1741 name: Unchanged("F".into()),
1742 cake_id: Set(Some(4)),
1743 }
1744 );
1745
1746 assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1747
1748 assert_eq!(
1749 fruit,
1750 fruit::ActiveModel {
1751 id: Unchanged(2),
1752 name: Unchanged("F".into()),
1753 cake_id: Set(None),
1754 }
1755 );
1756
1757 let mut cake_filling = cake_filling::ActiveModel::new();
1758
1759 cake_filling.set_parent_key(&cake).unwrap();
1760
1761 assert_eq!(
1762 cake_filling,
1763 cake_filling::ActiveModel {
1764 cake_id: Set(4),
1765 filling_id: NotSet,
1766 }
1767 );
1768 }
1769}