Skip to main content

sea_orm/entity/
active_model.rs

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