sea_orm/entity/
active_model.rs

1use crate::{
2    ColumnTrait, ConnectionTrait, DeleteResult, EntityTrait, Iterable, PrimaryKeyArity,
3    PrimaryKeyToColumn, PrimaryKeyTrait, Value, error::*,
4};
5use async_trait::async_trait;
6use sea_query::{Nullable, ValueTuple};
7use std::fmt::Debug;
8
9pub use ActiveValue::{NotSet, Set, Unchanged};
10
11/// The state of a field in an [ActiveModel][ActiveModelTrait].
12///
13/// There are three possible states represented by three enum variants:
14///
15/// - [Set] - a value that's explicitly set by the application and sent to the database.
16/// - [Unchanged] - an existing, unchanged value from the database.
17/// - [NotSet] - an undefined value (nothing is sent to the database).
18///
19/// The difference between these states is useful
20/// when constructing `INSERT` and `UPDATE` SQL statements (see an example below).
21/// It's also useful for knowing which fields have changed in a record.
22///
23/// # Examples
24///
25/// ```
26/// use sea_orm::tests_cfg::{cake, fruit};
27/// use sea_orm::{DbBackend, entity::*, query::*};
28///
29/// // Here, we use `NotSet` to let the database automatically generate an `id`.
30/// // This is different from `Set(None)` that explicitly sets `cake_id` to `NULL`.
31/// assert_eq!(
32///     Insert::one(fruit::ActiveModel {
33///         id: ActiveValue::NotSet,
34///         name: ActiveValue::Set("Orange".to_owned()),
35///         cake_id: ActiveValue::Set(None),
36///     })
37///     .build(DbBackend::Postgres)
38///     .to_string(),
39///     r#"INSERT INTO "fruit" ("name", "cake_id") VALUES ('Orange', NULL)"#
40/// );
41///
42/// // Here, we update the record, set `cake_id` to the new value
43/// // and use `NotSet` to avoid updating the `name` field.
44/// // `id` is the primary key, so it's used in the condition and not updated.
45/// assert_eq!(
46///     Update::one(fruit::ActiveModel {
47///         id: ActiveValue::Unchanged(1),
48///         name: ActiveValue::NotSet,
49///         cake_id: ActiveValue::Set(Some(2)),
50///     })
51///     .validate()
52///     .unwrap()
53///     .build(DbBackend::Postgres)
54///     .to_string(),
55///     r#"UPDATE "fruit" SET "cake_id" = 2 WHERE "fruit"."id" = 1"#
56/// );
57/// ```
58#[derive(Clone, Debug)]
59pub enum ActiveValue<V>
60where
61    V: Into<Value>,
62{
63    /// A [Value] that's explicitly set by the application and sent to the database.
64    ///
65    /// Use this to insert or set a specific value.
66    ///
67    /// When editing an existing value, you can use [set_if_not_equals][ActiveValue::set_if_not_equals]
68    /// to preserve the [Unchanged] state when the new value is the same as the old one.
69    /// Then you can meaningfully use methods like [ActiveModelTrait::is_changed].
70    Set(V),
71    /// An existing, unchanged [Value] from the database.
72    ///
73    /// You get these when you query an existing [Model][crate::ModelTrait]
74    /// from the database and convert it into an [ActiveModel][ActiveModelTrait].
75    ///
76    /// When you edit it, you can use [set_if_not_equals][ActiveValue::set_if_not_equals]
77    /// to preserve this "unchanged" state if the new value is the same as the old one.
78    /// Then you can meaningfully use methods like [ActiveModelTrait::is_changed].
79    Unchanged(V),
80    /// An undefined [Value]. Nothing is sent to the database.
81    ///
82    /// When you create a new [ActiveModel][ActiveModelTrait],
83    /// its fields are [NotSet][ActiveValue::NotSet] by default.
84    ///
85    /// This can be useful when:
86    ///
87    /// - You insert a new record and want the database to generate a default value (e.g., an id).
88    /// - In an `UPDATE` statement, you don't want to update some field.
89    NotSet,
90}
91
92/// Defines an not set operation on an [ActiveValue]
93#[deprecated(
94    since = "0.5.0",
95    note = "Please use [`ActiveValue::NotSet`] or [`NotSet`]"
96)]
97#[allow(non_snake_case)]
98pub fn Unset<V>(_: Option<bool>) -> ActiveValue<V>
99where
100    V: Into<Value>,
101{
102    ActiveValue::not_set()
103}
104
105/// `ActiveModel` is a type for constructing `INSERT` and `UPDATE` statements for a particular table.
106///
107/// Like [Model][ModelTrait], it represents a database record and each field represents a column.
108///
109/// But unlike [Model][ModelTrait], it also stores [additional state][ActiveValue] for every field,
110/// and fields are not guaranteed to have a value.
111///
112/// This allows you to:
113///
114/// - omit columns from the query,
115/// - know which columns have changed after editing a record.
116#[async_trait]
117pub trait ActiveModelTrait: Clone + Debug {
118    /// The Entity this ActiveModel belongs to
119    type Entity: EntityTrait;
120
121    /// Get a mutable [ActiveValue] from an ActiveModel
122    fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
123
124    /// Get a immutable [ActiveValue] from an ActiveModel
125    fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
126
127    /// Set the Value of a ActiveModel field, panic if failed
128    fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
129        self.try_set(c, v)
130            .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
131    }
132
133    /// Set the Value of a ActiveModel field, return error if failed
134    fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
135
136    /// Set the state of an [ActiveValue] to the not set state
137    fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
138
139    /// Check the state of a [ActiveValue]
140    fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
141
142    /// Create an ActiveModel with all fields to NotSet
143    fn default() -> Self;
144
145    /// Create an ActiveModel with all fields to Set(default_value) if Default is implemented, NotSet otherwise
146    fn default_values() -> Self;
147
148    /// Reset the value from [ActiveValue::Unchanged] to [ActiveValue::Set],
149    /// leaving [ActiveValue::NotSet] untouched.
150    fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
151
152    /// Reset all values from [ActiveValue::Unchanged] to [ActiveValue::Set],
153    /// leaving [ActiveValue::NotSet] untouched.
154    fn reset_all(mut self) -> Self {
155        for col in <Self::Entity as EntityTrait>::Column::iter() {
156            self.reset(col);
157        }
158        self
159    }
160
161    /// Get the primary key of the ActiveModel, if it's fully specified.
162    fn get_primary_key_value(&self) -> Option<ValueTuple> {
163        let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
164        macro_rules! next {
165            () => {
166                self.get(cols.next()?.into_column()).into_value()?
167            };
168        }
169        match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
170            1 => {
171                let s1 = next!();
172                Some(ValueTuple::One(s1))
173            }
174            2 => {
175                let s1 = next!();
176                let s2 = next!();
177                Some(ValueTuple::Two(s1, s2))
178            }
179            3 => {
180                let s1 = next!();
181                let s2 = next!();
182                let s3 = next!();
183                Some(ValueTuple::Three(s1, s2, s3))
184            }
185            len => {
186                let mut vec = Vec::with_capacity(len);
187                for _ in 0..len {
188                    let s = next!();
189                    vec.push(s);
190                }
191                Some(ValueTuple::Many(vec))
192            }
193        }
194    }
195
196    /// Perform an `INSERT` operation on the ActiveModel
197    ///
198    /// # Example (Postgres)
199    ///
200    /// ```
201    /// # use sea_orm::{error::*, tests_cfg::*, *};
202    /// #
203    /// # #[smol_potat::main]
204    /// # #[cfg(feature = "mock")]
205    /// # pub async fn main() -> Result<(), DbErr> {
206    /// #
207    /// # let db = MockDatabase::new(DbBackend::Postgres)
208    /// #     .append_query_results([
209    /// #         [cake::Model {
210    /// #             id: 15,
211    /// #             name: "Apple Pie".to_owned(),
212    /// #         }],
213    /// #     ])
214    /// #     .into_connection();
215    /// #
216    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
217    ///
218    /// let apple = cake::ActiveModel {
219    ///     name: Set("Apple Pie".to_owned()),
220    ///     ..Default::default()
221    /// };
222    ///
223    /// assert_eq!(
224    ///     apple.insert(&db).await?,
225    ///     cake::Model {
226    ///         id: 15,
227    ///         name: "Apple Pie".to_owned(),
228    ///     }
229    /// );
230    ///
231    /// assert_eq!(
232    ///     db.into_transaction_log(),
233    ///     [Transaction::from_sql_and_values(
234    ///         DbBackend::Postgres,
235    ///         r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id", "name""#,
236    ///         ["Apple Pie".into()]
237    ///     )]
238    /// );
239    /// #
240    /// # Ok(())
241    /// # }
242    /// ```
243    ///
244    /// # Example (MySQL)
245    ///
246    /// ```
247    /// # use sea_orm::{error::*, tests_cfg::*, *};
248    /// #
249    /// # #[smol_potat::main]
250    /// # #[cfg(feature = "mock")]
251    /// # pub async fn main() -> Result<(), DbErr> {
252    /// #
253    /// # let db = MockDatabase::new(DbBackend::MySql)
254    /// #     .append_query_results([
255    /// #         [cake::Model {
256    /// #             id: 15,
257    /// #             name: "Apple Pie".to_owned(),
258    /// #         }],
259    /// #     ])
260    /// #     .append_exec_results([
261    /// #         MockExecResult {
262    /// #             last_insert_id: 15,
263    /// #             rows_affected: 1,
264    /// #         },
265    /// #     ])
266    /// #     .into_connection();
267    /// #
268    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
269    ///
270    /// let apple = cake::ActiveModel {
271    ///     name: Set("Apple Pie".to_owned()),
272    ///     ..Default::default()
273    /// };
274    ///
275    /// assert_eq!(
276    ///     apple.insert(&db).await?,
277    ///     cake::Model {
278    ///         id: 15,
279    ///         name: "Apple Pie".to_owned(),
280    ///     }
281    /// );
282    ///
283    /// assert_eq!(
284    ///     db.into_transaction_log(),
285    ///     [
286    ///         Transaction::from_sql_and_values(
287    ///             DbBackend::MySql,
288    ///             r#"INSERT INTO `cake` (`name`) VALUES (?)"#,
289    ///             ["Apple Pie".into()]
290    ///         ),
291    ///         Transaction::from_sql_and_values(
292    ///             DbBackend::MySql,
293    ///             r#"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = ? LIMIT ?"#,
294    ///             [15.into(), 1u64.into()]
295    ///         )
296    ///     ]
297    /// );
298    /// #
299    /// # Ok(())
300    /// # }
301    /// ```
302    async fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
303    where
304        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
305        Self: ActiveModelBehavior + 'a,
306        C: ConnectionTrait,
307    {
308        let am = ActiveModelBehavior::before_save(self, db, true).await?;
309        let model = <Self::Entity as EntityTrait>::insert(am)
310            .exec_with_returning(db)
311            .await?;
312        Self::after_save(model, db, true).await
313    }
314
315    /// Perform the `UPDATE` operation on an ActiveModel
316    ///
317    /// # Example (Postgres)
318    ///
319    /// ```
320    /// # use sea_orm::{error::*, tests_cfg::*, *};
321    /// #
322    /// # #[smol_potat::main]
323    /// # #[cfg(feature = "mock")]
324    /// # pub async fn main() -> Result<(), DbErr> {
325    /// #
326    /// # let db = MockDatabase::new(DbBackend::Postgres)
327    /// #     .append_query_results([
328    /// #         [fruit::Model {
329    /// #             id: 1,
330    /// #             name: "Orange".to_owned(),
331    /// #             cake_id: None,
332    /// #         }],
333    /// #     ])
334    /// #     .into_connection();
335    /// #
336    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
337    ///
338    /// let orange = fruit::ActiveModel {
339    ///     id: Set(1),
340    ///     name: Set("Orange".to_owned()),
341    ///     ..Default::default()
342    /// };
343    ///
344    /// assert_eq!(
345    ///     orange.update(&db).await?,
346    ///     fruit::Model {
347    ///         id: 1,
348    ///         name: "Orange".to_owned(),
349    ///         cake_id: None,
350    ///     }
351    /// );
352    ///
353    /// assert_eq!(
354    ///     db.into_transaction_log(),
355    ///     [Transaction::from_sql_and_values(
356    ///         DbBackend::Postgres,
357    ///         r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2 RETURNING "id", "name", "cake_id""#,
358    ///         ["Orange".into(), 1i32.into()]
359    ///     )]);
360    /// #
361    /// # Ok(())
362    /// # }
363    /// ```
364    ///
365    /// # Example (MySQL)
366    ///
367    /// ```
368    /// # use sea_orm::{error::*, tests_cfg::*, *};
369    /// #
370    /// # #[smol_potat::main]
371    /// # #[cfg(feature = "mock")]
372    /// # pub async fn main() -> Result<(), DbErr> {
373    /// #
374    /// # let db = MockDatabase::new(DbBackend::MySql)
375    /// #     .append_query_results([
376    /// #         [fruit::Model {
377    /// #             id: 1,
378    /// #             name: "Orange".to_owned(),
379    /// #             cake_id: None,
380    /// #         }],
381    /// #     ])
382    /// #     .append_exec_results([
383    /// #         MockExecResult {
384    /// #             last_insert_id: 0,
385    /// #             rows_affected: 1,
386    /// #         },
387    /// #     ])
388    /// #     .into_connection();
389    /// #
390    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
391    ///
392    /// let orange = fruit::ActiveModel {
393    ///     id: Set(1),
394    ///     name: Set("Orange".to_owned()),
395    ///     ..Default::default()
396    /// };
397    ///
398    /// assert_eq!(
399    ///     orange.update(&db).await?,
400    ///     fruit::Model {
401    ///         id: 1,
402    ///         name: "Orange".to_owned(),
403    ///         cake_id: None,
404    ///     }
405    /// );
406    ///
407    /// assert_eq!(
408    ///     db.into_transaction_log(),
409    ///     [
410    ///         Transaction::from_sql_and_values(
411    ///             DbBackend::MySql,
412    ///             r#"UPDATE `fruit` SET `name` = ? WHERE `fruit`.`id` = ?"#,
413    ///             ["Orange".into(), 1i32.into()]
414    ///         ),
415    ///         Transaction::from_sql_and_values(
416    ///             DbBackend::MySql,
417    ///             r#"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = ? LIMIT ?"#,
418    ///             [1i32.into(), 1u64.into()]
419    ///         )]);
420    /// #
421    /// # Ok(())
422    /// # }
423    /// ```
424    async fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
425    where
426        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
427        Self: ActiveModelBehavior + 'a,
428        C: ConnectionTrait,
429    {
430        let am = ActiveModelBehavior::before_save(self, db, false).await?;
431        let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db).await?;
432        Self::after_save(model, db, false).await
433    }
434
435    /// Insert the model if primary key is `NotSet`, update otherwise.
436    /// Only works if the entity has auto increment primary key.
437    async fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
438    where
439        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
440        Self: ActiveModelBehavior + 'a,
441        C: ConnectionTrait,
442    {
443        let mut is_update = true;
444        for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
445            let col = key.into_column();
446            if self.is_not_set(col) {
447                is_update = false;
448                break;
449            }
450        }
451        let res = if !is_update {
452            self.insert(db).await
453        } else {
454            self.update(db).await
455        }?;
456        Ok(res.into_active_model())
457    }
458
459    /// Delete an active model by its primary key
460    ///
461    /// # Example
462    ///
463    /// ```
464    /// # use sea_orm::{error::*, tests_cfg::*, *};
465    /// #
466    /// # #[smol_potat::main]
467    /// # #[cfg(feature = "mock")]
468    /// # pub async fn main() -> Result<(), DbErr> {
469    /// #
470    /// # let db = MockDatabase::new(DbBackend::Postgres)
471    /// #     .append_exec_results([
472    /// #         MockExecResult {
473    /// #             last_insert_id: 0,
474    /// #             rows_affected: 1,
475    /// #         },
476    /// #     ])
477    /// #     .into_connection();
478    /// #
479    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
480    ///
481    /// let orange = fruit::ActiveModel {
482    ///     id: Set(3),
483    ///     ..Default::default()
484    /// };
485    ///
486    /// let delete_result = orange.delete(&db).await?;
487    ///
488    /// assert_eq!(delete_result.rows_affected, 1);
489    ///
490    /// assert_eq!(
491    ///     db.into_transaction_log(),
492    ///     [Transaction::from_sql_and_values(
493    ///         DbBackend::Postgres,
494    ///         r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
495    ///         [3i32.into()]
496    ///     )]
497    /// );
498    /// #
499    /// # Ok(())
500    /// # }
501    /// ```
502    async fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
503    where
504        Self: ActiveModelBehavior + 'a,
505        C: ConnectionTrait,
506    {
507        let am = ActiveModelBehavior::before_delete(self, db).await?;
508        let am_clone = am.clone();
509        let delete_res = Self::Entity::delete(am).exec(db).await?;
510        ActiveModelBehavior::after_delete(am_clone, db).await?;
511        Ok(delete_res)
512    }
513
514    /// Set the corresponding attributes in the ActiveModel from a JSON value
515    ///
516    /// Note that this method will not alter the primary key values in ActiveModel.
517    #[cfg(feature = "with-json")]
518    fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
519    where
520        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
521        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
522        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
523            serde::de::Deserialize<'de> + serde::Serialize,
524    {
525        use crate::Iterable;
526
527        // Backup primary key values
528        let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
529            <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
530                .map(|pk| (pk.into_column(), self.take(pk.into_column())))
531                .collect();
532
533        // Replace all values in ActiveModel
534        *self = Self::from_json(json)?;
535
536        // Restore primary key values
537        for (col, active_value) in primary_key_values {
538            match active_value {
539                ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
540                NotSet => self.not_set(col),
541            }
542        }
543
544        Ok(())
545    }
546
547    /// Create ActiveModel from a JSON value
548    #[cfg(feature = "with-json")]
549    fn from_json(mut json: serde_json::Value) -> Result<Self, DbErr>
550    where
551        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
552        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
553        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
554            serde::de::Deserialize<'de> + serde::Serialize,
555    {
556        use crate::{IdenStatic, Iterable};
557
558        let serde_json::Value::Object(obj) = &json else {
559            return Err(DbErr::Json(format!(
560                "invalid type: expected JSON object for {}",
561                <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
562            )));
563        };
564
565        // Mark down which attribute exists in the JSON object
566        let mut json_keys: Vec<(<Self::Entity as EntityTrait>::Column, bool)> = Vec::new();
567
568        for col in <<Self::Entity as EntityTrait>::Column>::iter() {
569            let key = col.as_str();
570            let has_key = obj.contains_key(key);
571            json_keys.push((col, has_key));
572        }
573
574        // Create dummy model with dummy values
575        let dummy_model = Self::default_values();
576        if let Ok(dummy_model) = dummy_model.try_into_model() {
577            if let Ok(mut dummy_json) = serde_json::to_value(&dummy_model) {
578                let serde_json::Value::Object(merged) = &mut dummy_json else {
579                    unreachable!();
580                };
581                let serde_json::Value::Object(obj) = json else {
582                    unreachable!();
583                };
584                // overwrite dummy values with input values
585                for (key, value) in obj {
586                    merged.insert(key, value);
587                }
588                json = dummy_json;
589            }
590        }
591
592        // Convert JSON object into ActiveModel via Model
593        let model: <Self::Entity as EntityTrait>::Model =
594            serde_json::from_value(json).map_err(json_err)?;
595        let mut am = model.into_active_model();
596
597        // Transform attribute that exists in JSON object into ActiveValue::Set, otherwise ActiveValue::NotSet
598        for (col, json_key_exists) in json_keys {
599            match (json_key_exists, am.get(col)) {
600                (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
601                    am.set(col, value);
602                }
603                _ => {
604                    am.not_set(col);
605                }
606            }
607        }
608
609        Ok(am)
610    }
611
612    /// Return `true` if any attribute of `ActiveModel` is `Set`
613    fn is_changed(&self) -> bool {
614        <Self::Entity as EntityTrait>::Column::iter()
615            .any(|col| self.get(col).is_set() && !self.get(col).is_unchanged())
616    }
617}
618
619/// A Trait for overriding the ActiveModel behavior
620///
621/// ### Example
622/// ```ignore
623/// use sea_orm::entity::prelude::*;
624///
625///  // Use [DeriveEntity] to derive the EntityTrait automatically
626/// #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
627/// pub struct Entity;
628///
629/// /// The [EntityName] describes the name of a table
630/// impl EntityName for Entity {
631///     fn table_name(&self) -> &'static str {
632///         "cake"
633///     }
634/// }
635///
636/// // Derive the ActiveModel
637/// #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
638/// pub struct Model {
639///     pub id: i32,
640///     pub name: String,
641/// }
642///
643/// impl ActiveModelBehavior for ActiveModel {}
644/// ```
645/// See module level docs [crate::entity] for a full example
646#[allow(unused_variables)]
647#[async_trait]
648pub trait ActiveModelBehavior: ActiveModelTrait {
649    /// Create a new ActiveModel with default values. Also used by `Default::default()`.
650    fn new() -> Self {
651        <Self as ActiveModelTrait>::default()
652    }
653
654    /// Will be called before `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
655    async fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
656    where
657        C: ConnectionTrait,
658    {
659        Ok(self)
660    }
661
662    /// Will be called after `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
663    async fn after_save<C>(
664        model: <Self::Entity as EntityTrait>::Model,
665        db: &C,
666        insert: bool,
667    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
668    where
669        C: ConnectionTrait,
670    {
671        Ok(model)
672    }
673
674    /// Will be called before `ActiveModel::delete`
675    async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
676    where
677        C: ConnectionTrait,
678    {
679        Ok(self)
680    }
681
682    /// Will be called after `ActiveModel::delete`
683    async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
684    where
685        C: ConnectionTrait,
686    {
687        Ok(self)
688    }
689}
690
691/// A Trait for any type that can be converted into an ActiveModel
692pub trait IntoActiveModel<A>
693where
694    A: ActiveModelTrait,
695{
696    /// Method to call to perform the conversion
697    fn into_active_model(self) -> A;
698}
699
700impl<A> IntoActiveModel<A> for A
701where
702    A: ActiveModelTrait,
703{
704    fn into_active_model(self) -> A {
705        self
706    }
707}
708
709/// Any type that can be converted into an [ActiveValue]
710pub trait IntoActiveValue<V>
711where
712    V: Into<Value>,
713{
714    /// Method to perform the conversion
715    fn into_active_value(self) -> ActiveValue<V>;
716}
717
718impl<V> IntoActiveValue<Option<V>> for Option<V>
719where
720    V: IntoActiveValue<V> + Into<Value> + Nullable,
721{
722    fn into_active_value(self) -> ActiveValue<Option<V>> {
723        match self {
724            Some(value) => Set(Some(value)),
725            None => NotSet,
726        }
727    }
728}
729
730impl<V> IntoActiveValue<Option<V>> for Option<Option<V>>
731where
732    V: IntoActiveValue<V> + Into<Value> + Nullable,
733{
734    fn into_active_value(self) -> ActiveValue<Option<V>> {
735        match self {
736            Some(value) => Set(value),
737            None => NotSet,
738        }
739    }
740}
741
742macro_rules! impl_into_active_value {
743    ($ty: ty) => {
744        impl IntoActiveValue<$ty> for $ty {
745            fn into_active_value(self) -> ActiveValue<$ty> {
746                Set(self)
747            }
748        }
749    };
750}
751
752impl_into_active_value!(bool);
753impl_into_active_value!(i8);
754impl_into_active_value!(i16);
755impl_into_active_value!(i32);
756impl_into_active_value!(i64);
757impl_into_active_value!(u8);
758impl_into_active_value!(u16);
759impl_into_active_value!(u32);
760impl_into_active_value!(u64);
761impl_into_active_value!(f32);
762impl_into_active_value!(f64);
763impl_into_active_value!(&'static str);
764impl_into_active_value!(String);
765impl_into_active_value!(Vec<u8>);
766
767#[cfg(feature = "with-json")]
768#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
769impl_into_active_value!(crate::prelude::Json);
770
771#[cfg(feature = "with-chrono")]
772#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
773impl_into_active_value!(crate::prelude::Date);
774
775#[cfg(feature = "with-chrono")]
776#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
777impl_into_active_value!(crate::prelude::Time);
778
779#[cfg(feature = "with-chrono")]
780#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
781impl_into_active_value!(crate::prelude::DateTime);
782
783#[cfg(feature = "with-chrono")]
784#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
785impl_into_active_value!(crate::prelude::DateTimeWithTimeZone);
786
787#[cfg(feature = "with-chrono")]
788#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
789impl_into_active_value!(crate::prelude::DateTimeUtc);
790
791#[cfg(feature = "with-chrono")]
792#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
793impl_into_active_value!(crate::prelude::DateTimeLocal);
794
795#[cfg(feature = "with-rust_decimal")]
796#[cfg_attr(docsrs, doc(cfg(feature = "with-rust_decimal")))]
797impl_into_active_value!(crate::prelude::Decimal);
798
799#[cfg(feature = "with-bigdecimal")]
800#[cfg_attr(docsrs, doc(cfg(feature = "with-bigdecimal")))]
801impl_into_active_value!(crate::prelude::BigDecimal);
802
803#[cfg(feature = "with-uuid")]
804#[cfg_attr(docsrs, doc(cfg(feature = "with-uuid")))]
805impl_into_active_value!(crate::prelude::Uuid);
806
807#[cfg(feature = "with-time")]
808#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
809impl_into_active_value!(crate::prelude::TimeDate);
810
811#[cfg(feature = "with-time")]
812#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
813impl_into_active_value!(crate::prelude::TimeTime);
814
815#[cfg(feature = "with-time")]
816#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
817impl_into_active_value!(crate::prelude::TimeDateTime);
818
819#[cfg(feature = "with-time")]
820#[cfg_attr(docsrs, doc(cfg(feature = "with-time")))]
821impl_into_active_value!(crate::prelude::TimeDateTimeWithTimeZone);
822
823#[cfg(feature = "with-ipnetwork")]
824#[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))]
825impl_into_active_value!(crate::prelude::IpNetwork);
826
827impl<V> Default for ActiveValue<V>
828where
829    V: Into<Value>,
830{
831    /// Create an [ActiveValue::NotSet]
832    fn default() -> Self {
833        Self::NotSet
834    }
835}
836
837impl<V> ActiveValue<V>
838where
839    V: Into<Value>,
840{
841    /// Create an [ActiveValue::Set]
842    pub fn set(value: V) -> Self {
843        Self::Set(value)
844    }
845
846    /// Check if the [ActiveValue] is [ActiveValue::Set]
847    pub fn is_set(&self) -> bool {
848        matches!(self, Self::Set(_))
849    }
850
851    /// Create an [ActiveValue::Unchanged]
852    pub fn unchanged(value: V) -> Self {
853        Self::Unchanged(value)
854    }
855
856    /// Check if the [ActiveValue] is [ActiveValue::Unchanged]
857    pub fn is_unchanged(&self) -> bool {
858        matches!(self, Self::Unchanged(_))
859    }
860
861    /// Create an [ActiveValue::NotSet]
862    pub fn not_set() -> Self {
863        Self::default()
864    }
865
866    /// Check if the [ActiveValue] is [ActiveValue::NotSet]
867    pub fn is_not_set(&self) -> bool {
868        matches!(self, Self::NotSet)
869    }
870
871    /// Get the mutable value an [ActiveValue]
872    /// also setting itself to [ActiveValue::NotSet]
873    pub fn take(&mut self) -> Option<V> {
874        match std::mem::take(self) {
875            ActiveValue::Set(value) | ActiveValue::Unchanged(value) => Some(value),
876            ActiveValue::NotSet => None,
877        }
878    }
879
880    /// Get an owned value of the [ActiveValue]
881    ///
882    /// # Panics
883    ///
884    /// Panics if it is [ActiveValue::NotSet]
885    pub fn unwrap(self) -> V {
886        match self {
887            ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value,
888            ActiveValue::NotSet => panic!("Cannot unwrap ActiveValue::NotSet"),
889        }
890    }
891
892    /// Check if a [Value] exists or not
893    pub fn into_value(self) -> Option<Value> {
894        match self {
895            ActiveValue::Set(value) | ActiveValue::Unchanged(value) => Some(value.into()),
896            ActiveValue::NotSet => None,
897        }
898    }
899
900    /// Wrap the [Value] into a `ActiveValue<Value>`
901    pub fn into_wrapped_value(self) -> ActiveValue<Value> {
902        match self {
903            Self::Set(value) => ActiveValue::set(value.into()),
904            Self::Unchanged(value) => ActiveValue::unchanged(value.into()),
905            Self::NotSet => ActiveValue::not_set(),
906        }
907    }
908
909    /// Reset the value from [ActiveValue::Unchanged] to [ActiveValue::Set],
910    /// leaving [ActiveValue::NotSet] untouched.
911    pub fn reset(&mut self) {
912        *self = match self.take() {
913            Some(value) => ActiveValue::Set(value),
914            None => ActiveValue::NotSet,
915        };
916    }
917
918    /// `Set(value)`, except when [`self.is_unchanged()`][ActiveValue#method.is_unchanged]
919    /// and `value` equals the current [Unchanged][ActiveValue::Unchanged] value.
920    ///
921    /// This is useful when you have an [Unchanged][ActiveValue::Unchanged] value from the database,
922    /// then update it using this method,
923    /// and then use [`.is_unchanged()`][ActiveValue#method.is_unchanged] to see whether it has *actually* changed.
924    ///
925    /// The same nice effect applies to the entire `ActiveModel`.
926    /// You can now meaningfully use [ActiveModelTrait::is_changed][ActiveModelTrait#method.is_changed]
927    /// to see whether are any changes that need to be saved to the database.
928    ///
929    /// ## Examples
930    ///
931    /// ```
932    /// # use sea_orm::ActiveValue;
933    /// #
934    /// let mut value = ActiveValue::Unchanged("old");
935    ///
936    /// // This wouldn't be the case if we used plain `value = Set("old");`
937    /// value.set_if_not_equals("old");
938    /// assert!(value.is_unchanged());
939    ///
940    /// // Only when we change the actual `&str` value, it becomes `Set`
941    /// value.set_if_not_equals("new");
942    /// assert_eq!(value.is_unchanged(), false);
943    /// assert_eq!(value, ActiveValue::Set("new"));
944    /// ```
945    pub fn set_if_not_equals(&mut self, value: V)
946    where
947        V: PartialEq,
948    {
949        match self {
950            ActiveValue::Unchanged(current) if &value == current => {}
951            _ => *self = ActiveValue::Set(value),
952        }
953    }
954
955    /// Get the inner value, unless `self` is [NotSet][ActiveValue::NotSet].
956    ///
957    /// There's also a panicking version: [ActiveValue::as_ref].
958    ///
959    /// ## Examples
960    ///
961    /// ```
962    /// # use sea_orm::ActiveValue;
963    /// #
964    /// assert_eq!(ActiveValue::Unchanged(42).try_as_ref(), Some(&42));
965    /// assert_eq!(ActiveValue::Set(42).try_as_ref(), Some(&42));
966    /// assert_eq!(ActiveValue::NotSet.try_as_ref(), None::<&i32>);
967    /// ```
968    pub fn try_as_ref(&self) -> Option<&V> {
969        match self {
970            ActiveValue::Set(value) | ActiveValue::Unchanged(value) => Some(value),
971            ActiveValue::NotSet => None,
972        }
973    }
974}
975
976impl<V> std::convert::AsRef<V> for ActiveValue<V>
977where
978    V: Into<Value>,
979{
980    /// # Panics
981    ///
982    /// Panics if it is [ActiveValue::NotSet].
983    ///
984    /// See [ActiveValue::try_as_ref] for a fallible non-panicking version.
985    fn as_ref(&self) -> &V {
986        match self {
987            ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value,
988            ActiveValue::NotSet => panic!("Cannot borrow ActiveValue::NotSet"),
989        }
990    }
991}
992
993impl<V> PartialEq for ActiveValue<V>
994where
995    V: Into<Value> + std::cmp::PartialEq,
996{
997    fn eq(&self, other: &Self) -> bool {
998        match (self, other) {
999            (ActiveValue::Set(l), ActiveValue::Set(r)) => l == r,
1000            (ActiveValue::Unchanged(l), ActiveValue::Unchanged(r)) => l == r,
1001            (ActiveValue::NotSet, ActiveValue::NotSet) => true,
1002            _ => false,
1003        }
1004    }
1005}
1006
1007impl<V> From<ActiveValue<V>> for ActiveValue<Option<V>>
1008where
1009    V: Into<Value> + Nullable,
1010{
1011    fn from(value: ActiveValue<V>) -> Self {
1012        match value {
1013            ActiveValue::Set(value) => ActiveValue::set(Some(value)),
1014            ActiveValue::Unchanged(value) => ActiveValue::unchanged(Some(value)),
1015            ActiveValue::NotSet => ActiveValue::not_set(),
1016        }
1017    }
1018}
1019
1020#[cfg(test)]
1021mod tests {
1022    use crate::{DbErr, entity::*, tests_cfg::*};
1023    use pretty_assertions::assert_eq;
1024
1025    #[cfg(feature = "with-json")]
1026    use serde_json::json;
1027
1028    #[test]
1029    #[cfg(feature = "macros")]
1030    fn test_derive_into_active_model_1() {
1031        mod my_fruit {
1032            pub use super::fruit::*;
1033            use crate as sea_orm;
1034            use crate::entity::prelude::*;
1035
1036            #[derive(DeriveIntoActiveModel)]
1037            pub struct NewFruit {
1038                // id is omitted
1039                pub name: String,
1040                // it is required as opposed to optional in Model
1041                pub cake_id: i32,
1042            }
1043        }
1044
1045        assert_eq!(
1046            my_fruit::NewFruit {
1047                name: "Apple".to_owned(),
1048                cake_id: 1,
1049            }
1050            .into_active_model(),
1051            fruit::ActiveModel {
1052                id: NotSet,
1053                name: Set("Apple".to_owned()),
1054                cake_id: Set(Some(1)),
1055            }
1056        );
1057    }
1058
1059    #[test]
1060    #[cfg(feature = "macros")]
1061    fn test_derive_into_active_model_2() {
1062        use crate as sea_orm;
1063        use crate::entity::prelude::*;
1064
1065        #[derive(DeriveIntoActiveModel)]
1066        #[sea_orm(active_model = "fruit::ActiveModel")]
1067        struct FruitName {
1068            name: String,
1069        }
1070
1071        assert_eq!(
1072            FruitName {
1073                name: "Apple Pie".to_owned(),
1074            }
1075            .into_active_model(),
1076            fruit::ActiveModel {
1077                id: NotSet,
1078                name: Set("Apple Pie".to_owned()),
1079                cake_id: NotSet,
1080            }
1081        );
1082
1083        #[derive(DeriveIntoActiveModel)]
1084        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1085        struct FruitCake {
1086            cake_id: Option<Option<i32>>,
1087        }
1088
1089        assert_eq!(
1090            FruitCake {
1091                cake_id: Some(Some(1)),
1092            }
1093            .into_active_model(),
1094            fruit::ActiveModel {
1095                id: NotSet,
1096                name: NotSet,
1097                cake_id: Set(Some(1)),
1098            }
1099        );
1100
1101        assert_eq!(
1102            FruitCake {
1103                cake_id: Some(None),
1104            }
1105            .into_active_model(),
1106            fruit::ActiveModel {
1107                id: NotSet,
1108                name: NotSet,
1109                cake_id: Set(None),
1110            }
1111        );
1112
1113        assert_eq!(
1114            FruitCake { cake_id: None }.into_active_model(),
1115            fruit::ActiveModel {
1116                id: NotSet,
1117                name: NotSet,
1118                cake_id: NotSet,
1119            }
1120        );
1121    }
1122
1123    #[test]
1124    #[cfg(feature = "macros")]
1125    fn test_derive_try_into_model_1() {
1126        mod my_fruit {
1127            use crate as sea_orm;
1128            use crate::entity::prelude::*;
1129
1130            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1131            #[sea_orm(table_name = "fruit")]
1132            pub struct Model {
1133                #[sea_orm(primary_key)]
1134                pub id: i32,
1135                pub name: String,
1136                pub cake_id: Option<i32>,
1137            }
1138
1139            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1140            pub enum Relation {}
1141
1142            impl ActiveModelBehavior for ActiveModel {}
1143        }
1144        assert_eq!(
1145            my_fruit::ActiveModel {
1146                id: Set(1),
1147                name: Set("Pineapple".to_owned()),
1148                cake_id: Set(None),
1149            }
1150            .try_into_model()
1151            .unwrap(),
1152            my_fruit::Model {
1153                id: 1,
1154                name: "Pineapple".to_owned(),
1155                cake_id: None,
1156            }
1157        );
1158
1159        assert_eq!(
1160            my_fruit::ActiveModel {
1161                id: Set(2),
1162                name: Set("Apple".to_owned()),
1163                cake_id: Set(Some(1)),
1164            }
1165            .try_into_model()
1166            .unwrap(),
1167            my_fruit::Model {
1168                id: 2,
1169                name: "Apple".to_owned(),
1170                cake_id: Some(1),
1171            }
1172        );
1173
1174        assert_eq!(
1175            my_fruit::ActiveModel {
1176                id: Set(1),
1177                name: NotSet,
1178                cake_id: Set(None),
1179            }
1180            .try_into_model(),
1181            Err(DbErr::AttrNotSet(String::from("name")))
1182        );
1183
1184        assert_eq!(
1185            my_fruit::ActiveModel {
1186                id: Set(1),
1187                name: Set("Pineapple".to_owned()),
1188                cake_id: NotSet,
1189            }
1190            .try_into_model(),
1191            Err(DbErr::AttrNotSet(String::from("cake_id")))
1192        );
1193    }
1194
1195    #[test]
1196    #[cfg(feature = "macros")]
1197    fn test_derive_try_into_model_2() {
1198        mod my_fruit {
1199            use crate as sea_orm;
1200            use crate::entity::prelude::*;
1201
1202            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1203            #[sea_orm(table_name = "fruit")]
1204            pub struct Model {
1205                #[sea_orm(primary_key)]
1206                pub id: i32,
1207                pub name: String,
1208                #[sea_orm(ignore)]
1209                pub cake_id: Option<i32>,
1210            }
1211
1212            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1213            pub enum Relation {}
1214
1215            impl ActiveModelBehavior for ActiveModel {}
1216        }
1217        assert_eq!(
1218            my_fruit::ActiveModel {
1219                id: Set(1),
1220                name: Set("Pineapple".to_owned()),
1221            }
1222            .try_into_model()
1223            .unwrap(),
1224            my_fruit::Model {
1225                id: 1,
1226                name: "Pineapple".to_owned(),
1227                cake_id: None,
1228            }
1229        );
1230    }
1231
1232    #[test]
1233    #[cfg(feature = "macros")]
1234    fn test_derive_try_into_model_3() {
1235        mod my_fruit {
1236            use crate as sea_orm;
1237            use crate::entity::prelude::*;
1238
1239            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1240            #[sea_orm(table_name = "fruit")]
1241            pub struct Model {
1242                #[sea_orm(primary_key)]
1243                pub id: i32,
1244                #[sea_orm(ignore)]
1245                pub name: String,
1246                pub cake_id: Option<i32>,
1247            }
1248
1249            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1250            pub enum Relation {}
1251
1252            impl ActiveModelBehavior for ActiveModel {}
1253        }
1254        assert_eq!(
1255            my_fruit::ActiveModel {
1256                id: Set(1),
1257                cake_id: Set(Some(1)),
1258            }
1259            .try_into_model()
1260            .unwrap(),
1261            my_fruit::Model {
1262                id: 1,
1263                name: "".to_owned(),
1264                cake_id: Some(1),
1265            }
1266        );
1267    }
1268
1269    #[test]
1270    #[cfg(feature = "with-json")]
1271    fn test_active_model_set_from_json_1() {
1272        assert_eq!(
1273            cake::ActiveModel::from_json(json!({
1274                "id": 1,
1275                "name": "Apple Pie",
1276            }))
1277            .unwrap(),
1278            cake::ActiveModel {
1279                id: Set(1),
1280                name: Set("Apple Pie".to_owned()),
1281            }
1282        );
1283
1284        assert_eq!(
1285            cake::ActiveModel::from_json(json!({
1286                "id": 1,
1287            }))
1288            .unwrap(),
1289            cake::ActiveModel {
1290                id: Set(1),
1291                name: NotSet,
1292            }
1293        );
1294
1295        assert_eq!(
1296            cake::ActiveModel::from_json(json!({
1297                "name": "Apple Pie",
1298            }))
1299            .unwrap(),
1300            cake::ActiveModel {
1301                id: NotSet,
1302                name: Set("Apple Pie".to_owned()),
1303            }
1304        );
1305
1306        let mut cake: cake::ActiveModel = Default::default();
1307        cake.set_from_json(json!({
1308            "name": "Apple Pie",
1309        }))
1310        .unwrap();
1311        assert_eq!(
1312            cake,
1313            cake::ActiveModel {
1314                id: NotSet,
1315                name: Set("Apple Pie".to_owned()),
1316            }
1317        );
1318    }
1319
1320    #[test]
1321    #[cfg(feature = "with-json")]
1322    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1323        let mut fruit: fruit::ActiveModel = Default::default();
1324
1325        fruit.set_from_json(json!({
1326            "name": "Apple",
1327        }))?;
1328        assert_eq!(
1329            fruit,
1330            fruit::ActiveModel {
1331                id: ActiveValue::NotSet,
1332                name: ActiveValue::Set("Apple".to_owned()),
1333                cake_id: ActiveValue::NotSet,
1334            }
1335        );
1336
1337        assert_eq!(
1338            fruit::ActiveModel::from_json(json!({
1339                "name": "Apple",
1340            }))?,
1341            fruit::ActiveModel {
1342                id: ActiveValue::NotSet,
1343                name: ActiveValue::Set("Apple".to_owned()),
1344                cake_id: ActiveValue::NotSet,
1345            }
1346        );
1347
1348        fruit.set_from_json(json!({
1349            "name": "Apple",
1350            "cake_id": null,
1351        }))?;
1352        assert_eq!(
1353            fruit,
1354            fruit::ActiveModel {
1355                id: ActiveValue::NotSet,
1356                name: ActiveValue::Set("Apple".to_owned()),
1357                cake_id: ActiveValue::Set(None),
1358            }
1359        );
1360
1361        fruit.set_from_json(json!({
1362            "id": null,
1363            "name": "Apple",
1364            "cake_id": 1,
1365        }))?;
1366        assert_eq!(
1367            fruit,
1368            fruit::ActiveModel {
1369                id: ActiveValue::NotSet,
1370                name: ActiveValue::Set("Apple".to_owned()),
1371                cake_id: ActiveValue::Set(Some(1)),
1372            }
1373        );
1374
1375        fruit.set_from_json(json!({
1376            "id": 2,
1377            "name": "Apple",
1378            "cake_id": 1,
1379        }))?;
1380        assert_eq!(
1381            fruit,
1382            fruit::ActiveModel {
1383                id: ActiveValue::NotSet,
1384                name: ActiveValue::Set("Apple".to_owned()),
1385                cake_id: ActiveValue::Set(Some(1)),
1386            }
1387        );
1388
1389        let mut fruit = fruit::ActiveModel {
1390            id: ActiveValue::Set(1),
1391            name: ActiveValue::NotSet,
1392            cake_id: ActiveValue::NotSet,
1393        };
1394        fruit.set_from_json(json!({
1395            "id": 8,
1396            "name": "Apple",
1397            "cake_id": 1,
1398        }))?;
1399        assert_eq!(
1400            fruit,
1401            fruit::ActiveModel {
1402                id: ActiveValue::Set(1),
1403                name: ActiveValue::Set("Apple".to_owned()),
1404                cake_id: ActiveValue::Set(Some(1)),
1405            }
1406        );
1407
1408        Ok(())
1409    }
1410
1411    #[smol_potat::test]
1412    #[cfg(feature = "with-json")]
1413    async fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1414        use crate::*;
1415
1416        let db = MockDatabase::new(DbBackend::Postgres)
1417            .append_exec_results([
1418                MockExecResult {
1419                    last_insert_id: 1,
1420                    rows_affected: 1,
1421                },
1422                MockExecResult {
1423                    last_insert_id: 1,
1424                    rows_affected: 1,
1425                },
1426            ])
1427            .append_query_results([
1428                [fruit::Model {
1429                    id: 1,
1430                    name: "Apple".to_owned(),
1431                    cake_id: None,
1432                }],
1433                [fruit::Model {
1434                    id: 2,
1435                    name: "Orange".to_owned(),
1436                    cake_id: Some(1),
1437                }],
1438            ])
1439            .into_connection();
1440
1441        let mut fruit: fruit::ActiveModel = Default::default();
1442        fruit.set_from_json(json!({
1443            "name": "Apple",
1444        }))?;
1445        fruit.save(&db).await?;
1446
1447        let mut fruit = fruit::ActiveModel {
1448            id: Set(2),
1449            ..Default::default()
1450        };
1451        fruit.set_from_json(json!({
1452            "id": 9,
1453            "name": "Orange",
1454            "cake_id": 1,
1455        }))?;
1456        fruit.save(&db).await?;
1457
1458        assert_eq!(
1459            db.into_transaction_log(),
1460            [
1461                Transaction::from_sql_and_values(
1462                    DbBackend::Postgres,
1463                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1464                    ["Apple".into()],
1465                ),
1466                Transaction::from_sql_and_values(
1467                    DbBackend::Postgres,
1468                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1469                    ["Orange".into(), 1i32.into(), 2i32.into()],
1470                ),
1471            ]
1472        );
1473
1474        Ok(())
1475    }
1476
1477    #[test]
1478    fn test_active_model_is_changed() {
1479        let mut fruit: fruit::ActiveModel = Default::default();
1480        assert!(!fruit.is_changed());
1481
1482        fruit.set(fruit::Column::Name, "apple".into());
1483        assert!(fruit.is_changed());
1484
1485        let mut fruit = fruit::Model {
1486            id: 1,
1487            name: "".into(),
1488            cake_id: None,
1489        };
1490        fruit.set("name".parse().unwrap(), "orange".into());
1491        assert_eq!(fruit.name, "orange");
1492    }
1493
1494    #[test]
1495    fn test_reset_1() {
1496        assert_eq!(
1497            fruit::Model {
1498                id: 1,
1499                name: "Apple".into(),
1500                cake_id: None,
1501            }
1502            .into_active_model(),
1503            fruit::ActiveModel {
1504                id: Unchanged(1),
1505                name: Unchanged("Apple".into()),
1506                cake_id: Unchanged(None)
1507            },
1508        );
1509
1510        assert_eq!(
1511            fruit::Model {
1512                id: 1,
1513                name: "Apple".into(),
1514                cake_id: None,
1515            }
1516            .into_active_model()
1517            .reset_all(),
1518            fruit::ActiveModel {
1519                id: Set(1),
1520                name: Set("Apple".into()),
1521                cake_id: Set(None)
1522            },
1523        );
1524
1525        assert_eq!(
1526            fruit::Model {
1527                id: 1,
1528                name: "Apple".into(),
1529                cake_id: Some(2),
1530            }
1531            .into_active_model(),
1532            fruit::ActiveModel {
1533                id: Unchanged(1),
1534                name: Unchanged("Apple".into()),
1535                cake_id: Unchanged(Some(2)),
1536            },
1537        );
1538
1539        assert_eq!(
1540            fruit::Model {
1541                id: 1,
1542                name: "Apple".into(),
1543                cake_id: Some(2),
1544            }
1545            .into_active_model()
1546            .reset_all(),
1547            fruit::ActiveModel {
1548                id: Set(1),
1549                name: Set("Apple".into()),
1550                cake_id: Set(Some(2)),
1551            },
1552        );
1553    }
1554
1555    #[smol_potat::test]
1556    async fn test_reset_2() -> Result<(), DbErr> {
1557        use crate::*;
1558
1559        let db = MockDatabase::new(DbBackend::Postgres)
1560            .append_exec_results(vec![
1561                MockExecResult {
1562                    last_insert_id: 1,
1563                    rows_affected: 1,
1564                },
1565                MockExecResult {
1566                    last_insert_id: 1,
1567                    rows_affected: 1,
1568                },
1569            ])
1570            .append_query_results(vec![
1571                vec![fruit::Model {
1572                    id: 1,
1573                    name: "Apple".to_owned(),
1574                    cake_id: None,
1575                }],
1576                vec![fruit::Model {
1577                    id: 1,
1578                    name: "Apple".to_owned(),
1579                    cake_id: None,
1580                }],
1581            ])
1582            .into_connection();
1583
1584        fruit::Model {
1585            id: 1,
1586            name: "Apple".into(),
1587            cake_id: None,
1588        }
1589        .into_active_model()
1590        .update(&db)
1591        .await?;
1592
1593        fruit::Model {
1594            id: 1,
1595            name: "Apple".into(),
1596            cake_id: None,
1597        }
1598        .into_active_model()
1599        .reset_all()
1600        .update(&db)
1601        .await?;
1602
1603        assert_eq!(
1604            db.into_transaction_log(),
1605            vec![
1606                Transaction::from_sql_and_values(
1607                    DbBackend::Postgres,
1608                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1609                    vec![1i32.into(), 1u64.into()],
1610                ),
1611                Transaction::from_sql_and_values(
1612                    DbBackend::Postgres,
1613                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1614                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1615                ),
1616            ]
1617        );
1618
1619        Ok(())
1620    }
1621
1622    #[test]
1623    fn test_active_model_default_values() {
1624        assert_eq!(
1625            fruit::ActiveModel::default_values(),
1626            fruit::ActiveModel {
1627                id: Set(0),
1628                name: Set("".into()),
1629                cake_id: Set(None),
1630            },
1631        );
1632
1633        assert_eq!(
1634            lunch_set::ActiveModel::default_values(),
1635            lunch_set::ActiveModel {
1636                id: Set(0),
1637                name: Set("".into()),
1638                tea: NotSet,
1639            },
1640        );
1641    }
1642}