sea_orm/entity/
active_model.rs

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/// `ActiveModel` is a type for constructing `INSERT` and `UPDATE` statements for a particular table.
16///
17/// Like [Model][ModelTrait], it represents a database record and each field represents a column.
18///
19/// But unlike [Model][ModelTrait], it also stores [additional state][ActiveValue] for every field,
20/// and fields are not guaranteed to have a value.
21///
22/// This allows you to:
23///
24/// - omit columns from the query,
25/// - know which columns have changed after editing a record.
26#[async_trait::async_trait]
27pub trait ActiveModelTrait: Clone + Debug {
28    /// The Entity this ActiveModel belongs to
29    type Entity: EntityTrait;
30
31    /// Get a mutable [ActiveValue] from an ActiveModel
32    fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
33
34    /// Get a immutable [ActiveValue] from an ActiveModel
35    fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
36
37    /// Set the Value of a ActiveModel field, panic if failed
38    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    /// Set the Value of a ActiveModel field if value is different, panic if failed
44    fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
45
46    /// Set the Value of a ActiveModel field, return error if failed
47    fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
48
49    /// Set the state of an [ActiveValue] to the not set state
50    fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
51
52    /// Check the state of a [ActiveValue]
53    fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
54
55    /// Create an ActiveModel with all fields to NotSet
56    fn default() -> Self;
57
58    /// Create an ActiveModel with all fields to Set(default_value) if Default is implemented, NotSet otherwise
59    fn default_values() -> Self;
60
61    /// Reset the value from [ActiveValue::Unchanged] to [ActiveValue::Set],
62    /// leaving [ActiveValue::NotSet] untouched.
63    fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
64
65    /// Reset all values from [ActiveValue::Unchanged] to [ActiveValue::Set],
66    /// leaving [ActiveValue::NotSet] untouched.
67    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    /// Get the primary key of the ActiveModel, only if it's fully specified.
75    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    /// Perform an `INSERT` operation on the ActiveModel
110    ///
111    /// # Example (Postgres)
112    ///
113    /// ```
114    /// # use sea_orm::{error::*, tests_cfg::*, *};
115    /// #
116    /// # #[smol_potat::main]
117    /// # #[cfg(feature = "mock")]
118    /// # pub async fn main() -> Result<(), DbErr> {
119    /// #
120    /// # let db = MockDatabase::new(DbBackend::Postgres)
121    /// #     .append_query_results([
122    /// #         [cake::Model {
123    /// #             id: 15,
124    /// #             name: "Apple Pie".to_owned(),
125    /// #         }],
126    /// #     ])
127    /// #     .into_connection();
128    /// #
129    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
130    ///
131    /// let apple = cake::ActiveModel {
132    ///     name: Set("Apple Pie".to_owned()),
133    ///     ..Default::default()
134    /// };
135    ///
136    /// assert_eq!(
137    ///     apple.insert(&db).await?,
138    ///     cake::Model {
139    ///         id: 15,
140    ///         name: "Apple Pie".to_owned(),
141    ///     }
142    /// );
143    ///
144    /// assert_eq!(
145    ///     db.into_transaction_log(),
146    ///     [Transaction::from_sql_and_values(
147    ///         DbBackend::Postgres,
148    ///         r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id", "name""#,
149    ///         ["Apple Pie".into()]
150    ///     )]
151    /// );
152    /// #
153    /// # Ok(())
154    /// # }
155    /// ```
156    ///
157    /// # Example (MySQL)
158    ///
159    /// ```
160    /// # use sea_orm::{error::*, tests_cfg::*, *};
161    /// #
162    /// # #[smol_potat::main]
163    /// # #[cfg(feature = "mock")]
164    /// # pub async fn main() -> Result<(), DbErr> {
165    /// #
166    /// # let db = MockDatabase::new(DbBackend::MySql)
167    /// #     .append_query_results([
168    /// #         [cake::Model {
169    /// #             id: 15,
170    /// #             name: "Apple Pie".to_owned(),
171    /// #         }],
172    /// #     ])
173    /// #     .append_exec_results([
174    /// #         MockExecResult {
175    /// #             last_insert_id: 15,
176    /// #             rows_affected: 1,
177    /// #         },
178    /// #     ])
179    /// #     .into_connection();
180    /// #
181    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
182    ///
183    /// let apple = cake::ActiveModel {
184    ///     name: Set("Apple Pie".to_owned()),
185    ///     ..Default::default()
186    /// };
187    ///
188    /// assert_eq!(
189    ///     apple.insert(&db).await?,
190    ///     cake::Model {
191    ///         id: 15,
192    ///         name: "Apple Pie".to_owned(),
193    ///     }
194    /// );
195    ///
196    /// assert_eq!(
197    ///     db.into_transaction_log(),
198    ///     [
199    ///         Transaction::from_sql_and_values(
200    ///             DbBackend::MySql,
201    ///             r#"INSERT INTO `cake` (`name`) VALUES (?)"#,
202    ///             ["Apple Pie".into()]
203    ///         ),
204    ///         Transaction::from_sql_and_values(
205    ///             DbBackend::MySql,
206    ///             r#"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = ? LIMIT ?"#,
207    ///             [15.into(), 1u64.into()]
208    ///         )
209    ///     ]
210    /// );
211    /// #
212    /// # Ok(())
213    /// # }
214    /// ```
215    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    /// Perform the `UPDATE` operation on an ActiveModel
229    ///
230    /// # Example (Postgres)
231    ///
232    /// ```
233    /// # use sea_orm::{error::*, tests_cfg::*, *};
234    /// #
235    /// # #[smol_potat::main]
236    /// # #[cfg(feature = "mock")]
237    /// # pub async fn main() -> Result<(), DbErr> {
238    /// #
239    /// # let db = MockDatabase::new(DbBackend::Postgres)
240    /// #     .append_query_results([
241    /// #         [fruit::Model {
242    /// #             id: 1,
243    /// #             name: "Orange".to_owned(),
244    /// #             cake_id: None,
245    /// #         }],
246    /// #     ])
247    /// #     .into_connection();
248    /// #
249    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
250    ///
251    /// let orange = fruit::ActiveModel {
252    ///     id: Set(1),
253    ///     name: Set("Orange".to_owned()),
254    ///     ..Default::default()
255    /// };
256    ///
257    /// assert_eq!(
258    ///     orange.update(&db).await?,
259    ///     fruit::Model {
260    ///         id: 1,
261    ///         name: "Orange".to_owned(),
262    ///         cake_id: None,
263    ///     }
264    /// );
265    ///
266    /// assert_eq!(
267    ///     db.into_transaction_log(),
268    ///     [Transaction::from_sql_and_values(
269    ///         DbBackend::Postgres,
270    ///         r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2 RETURNING "id", "name", "cake_id""#,
271    ///         ["Orange".into(), 1i32.into()]
272    ///     )]);
273    /// #
274    /// # Ok(())
275    /// # }
276    /// ```
277    ///
278    /// # Example (MySQL)
279    ///
280    /// ```
281    /// # use sea_orm::{error::*, tests_cfg::*, *};
282    /// #
283    /// # #[smol_potat::main]
284    /// # #[cfg(feature = "mock")]
285    /// # pub async fn main() -> Result<(), DbErr> {
286    /// #
287    /// # let db = MockDatabase::new(DbBackend::MySql)
288    /// #     .append_query_results([
289    /// #         [fruit::Model {
290    /// #             id: 1,
291    /// #             name: "Orange".to_owned(),
292    /// #             cake_id: None,
293    /// #         }],
294    /// #     ])
295    /// #     .append_exec_results([
296    /// #         MockExecResult {
297    /// #             last_insert_id: 0,
298    /// #             rows_affected: 1,
299    /// #         },
300    /// #     ])
301    /// #     .into_connection();
302    /// #
303    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
304    ///
305    /// let orange = fruit::ActiveModel {
306    ///     id: Set(1),
307    ///     name: Set("Orange".to_owned()),
308    ///     ..Default::default()
309    /// };
310    ///
311    /// assert_eq!(
312    ///     orange.update(&db).await?,
313    ///     fruit::Model {
314    ///         id: 1,
315    ///         name: "Orange".to_owned(),
316    ///         cake_id: None,
317    ///     }
318    /// );
319    ///
320    /// assert_eq!(
321    ///     db.into_transaction_log(),
322    ///     [
323    ///         Transaction::from_sql_and_values(
324    ///             DbBackend::MySql,
325    ///             r#"UPDATE `fruit` SET `name` = ? WHERE `fruit`.`id` = ?"#,
326    ///             ["Orange".into(), 1i32.into()]
327    ///         ),
328    ///         Transaction::from_sql_and_values(
329    ///             DbBackend::MySql,
330    ///             r#"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = ? LIMIT ?"#,
331    ///             [1i32.into(), 1u64.into()]
332    ///         )]);
333    /// #
334    /// # Ok(())
335    /// # }
336    /// ```
337    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    /// Insert the model if primary key is `NotSet`, update otherwise.
349    /// Only works if the entity has auto increment primary key.
350    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    /// Returns true if the primary key is fully-specified
365    #[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    /// Delete an active model by its primary key
379    ///
380    /// # Example
381    ///
382    /// ```
383    /// # use sea_orm::{error::*, tests_cfg::*, *};
384    /// #
385    /// # #[smol_potat::main]
386    /// # #[cfg(feature = "mock")]
387    /// # pub async fn main() -> Result<(), DbErr> {
388    /// #
389    /// # let db = MockDatabase::new(DbBackend::Postgres)
390    /// #     .append_exec_results([
391    /// #         MockExecResult {
392    /// #             last_insert_id: 0,
393    /// #             rows_affected: 1,
394    /// #         },
395    /// #     ])
396    /// #     .into_connection();
397    /// #
398    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
399    ///
400    /// let orange = fruit::ActiveModel {
401    ///     id: Set(3),
402    ///     ..Default::default()
403    /// };
404    ///
405    /// let delete_result = orange.delete(&db).await?;
406    ///
407    /// assert_eq!(delete_result.rows_affected, 1);
408    ///
409    /// assert_eq!(
410    ///     db.into_transaction_log(),
411    ///     [Transaction::from_sql_and_values(
412    ///         DbBackend::Postgres,
413    ///         r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
414    ///         [3i32.into()]
415    ///     )]
416    /// );
417    /// #
418    /// # Ok(())
419    /// # }
420    /// ```
421    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    /// Set the corresponding attributes in the ActiveModel from a JSON value
434    ///
435    /// Note that this method will not alter the primary key values in ActiveModel.
436    #[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        // Backup primary key values
447        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        // Replace all values in ActiveModel
453        *self = Self::from_json(json)?;
454
455        // Restore primary key values
456        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    /// Create ActiveModel from a JSON value
467    #[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        // Mark down which attribute exists in the JSON object
485        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        // Create dummy model with dummy values
494        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                // overwrite dummy values with input values
504                for (key, value) in obj {
505                    merged.insert(key, value);
506                }
507                json = dummy_json;
508            }
509        }
510
511        // Convert JSON object into ActiveModel via Model
512        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        // Transform attribute that exists in JSON object into ActiveValue::Set, otherwise ActiveValue::NotSet
517        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    /// Return `true` if any attribute of `ActiveModel` is `Set`
532    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    /// Set the key to parent's key value for a belongs to relation.
539    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    /// Clear parent association if the relation is optional and return true
632    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    /// Get the key value of belongs to relation
666    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    /// Get the key value of belongs to relation
686    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    /// Find related Models belonging to self
752    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    /// Establish links between self and a related Entity for a many-to-many relation.
770    /// New associations will be added, and leftovers can be optionally deleted.
771    #[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/// A Trait for overriding the ActiveModel behavior
904///
905/// ### Example
906/// ```ignore
907/// use sea_orm::entity::prelude::*;
908///
909///  // Use [DeriveEntity] to derive the EntityTrait automatically
910/// #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
911/// pub struct Entity;
912///
913/// /// The [EntityName] describes the name of a table
914/// impl EntityName for Entity {
915///     fn table_name(&self) -> &'static str {
916///         "cake"
917///     }
918/// }
919///
920/// // Derive the ActiveModel
921/// #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
922/// pub struct Model {
923///     pub id: i32,
924///     pub name: String,
925/// }
926///
927/// impl ActiveModelBehavior for ActiveModel {}
928/// ```
929/// See module level docs [crate::entity] for a full example
930#[allow(unused_variables)]
931#[async_trait::async_trait]
932pub trait ActiveModelBehavior: ActiveModelTrait {
933    /// Create a new ActiveModel with default values. This is also called by `Default::default()`.
934    ///
935    /// You can override it like the following:
936    ///
937    /// ```ignore
938    /// fn new() -> Self {
939    ///     Self {
940    ///         status: Set(Status::New),
941    ///         ..ActiveModelTrait::default()
942    ///     }
943    /// }
944    /// ```
945    fn new() -> Self {
946        <Self as ActiveModelTrait>::default()
947    }
948
949    /// Will be called before `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
950    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    /// Will be called after `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
958    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    /// Will be called before `ActiveModel::delete`
970    async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
971    where
972        C: ConnectionTrait,
973    {
974        Ok(self)
975    }
976
977    /// Will be called after `ActiveModel::delete`
978    async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
979    where
980        C: ConnectionTrait,
981    {
982        Ok(self)
983    }
984}
985
986/// A Trait for any type that can be converted into an ActiveModel
987pub trait IntoActiveModel<A>
988where
989    A: ActiveModelTrait,
990{
991    /// Method to call to perform the conversion
992    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        // if there are no related models, then there is no risk of insert conflict
1024        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        // if the primary key is a composite key of the two relations
1033        // we can use on conflict no action safely
1034        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; // un-mut
1049
1050    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            // if not already exist, save for insert
1060            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        // insert new junctions
1088        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                // id is omitted
1116                pub name: String,
1117                // it is required as opposed to optional in Model
1118                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}