sea_orm/entity/
active_model.rs

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