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