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    #[doc(hidden)]
753    fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
754    where
755        AM: ActiveModelTrait,
756        Self::Entity: Related<AM::Entity>,
757    {
758        self.find_related(AM::Entity::default())
759    }
760
761    /// Establish links between self and a related Entity for a many-to-many relation.
762    /// New associations will be added, and leftovers can be optionally deleted.
763    #[doc(hidden)]
764    fn establish_links<J, R, RM, C>(
765        &self,
766        _: J,
767        related_models: &[RM],
768        delete_leftover: bool,
769        db: &C,
770    ) -> Result<(), DbErr>
771    where
772        R: EntityTrait,
773        RM: ActiveModelTrait<Entity = R>,
774        J: EntityTrait + Related<R> + Related<Self::Entity>,
775        J::Model: IntoActiveModel<J::ActiveModel>,
776        J::ActiveModel: ActiveModelBehavior,
777        C: ConnectionTrait,
778    {
779        let left = <J as Related<Self::Entity>>::to();
780        let right = <J as Related<R>>::to();
781
782        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
783    }
784
785    #[doc(hidden)]
786    fn establish_links_self<J, RM, C>(
787        &self,
788        _: J,
789        related_models: &[RM],
790        delete_leftover: bool,
791        db: &C,
792    ) -> Result<(), DbErr>
793    where
794        RM: ActiveModelTrait<Entity = Self::Entity>,
795        J: EntityTrait,
796        J::Model: IntoActiveModel<J::ActiveModel>,
797        J::ActiveModel: ActiveModelBehavior,
798        C: ConnectionTrait,
799        Self::Entity: RelatedSelfVia<J>,
800    {
801        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
802        let right = <Self::Entity as RelatedSelfVia<J>>::to();
803
804        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
805    }
806
807    #[doc(hidden)]
808    fn establish_links_self_rev<J, RM, C>(
809        &self,
810        _: J,
811        related_models: &[RM],
812        delete_leftover: bool,
813        db: &C,
814    ) -> Result<(), DbErr>
815    where
816        RM: ActiveModelTrait<Entity = Self::Entity>,
817        J: EntityTrait,
818        J::Model: IntoActiveModel<J::ActiveModel>,
819        J::ActiveModel: ActiveModelBehavior,
820        C: ConnectionTrait,
821        Self::Entity: RelatedSelfVia<J>,
822    {
823        let left = <Self::Entity as RelatedSelfVia<J>>::to();
824        let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
825
826        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
827    }
828
829    #[doc(hidden)]
830    fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
831    where
832        J: EntityTrait + Related<Self::Entity>,
833        C: ConnectionTrait,
834    {
835        let rel_def = <J as Related<Self::Entity>>::to();
836        let id = get_key_from_active_model(&rel_def.to_col, self)?;
837
838        J::delete_many()
839            .filter(
840                column_tuple_in_condition(
841                    &rel_def.from_tbl,
842                    &rel_def.from_col,
843                    &[id],
844                    DbBackend::Sqlite,
845                )
846                .expect(""),
847            )
848            .exec(db)
849    }
850
851    #[doc(hidden)]
852    fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
853    where
854        J: EntityTrait,
855        C: ConnectionTrait,
856        Self::Entity: RelatedSelfVia<J>,
857    {
858        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
859        let right = <Self::Entity as RelatedSelfVia<J>>::to();
860
861        let id = get_key_from_active_model(&left.to_col, self)?;
862
863        if left.to_col != right.to_col {
864            return Err(DbErr::Type("Expect Self Referencing Relation".into()));
865        }
866
867        J::delete_many()
868            .filter(
869                Condition::any()
870                    .add(
871                        column_tuple_in_condition(
872                            &left.from_tbl,
873                            &left.from_col,
874                            std::slice::from_ref(&id),
875                            DbBackend::Sqlite,
876                        )
877                        .expect(""),
878                    )
879                    .add(
880                        column_tuple_in_condition(
881                            &right.from_tbl,
882                            &right.from_col,
883                            std::slice::from_ref(&id),
884                            DbBackend::Sqlite,
885                        )
886                        .expect(""),
887                    ),
888            )
889            .exec(db)
890    }
891}
892
893/// A Trait for overriding the ActiveModel behavior
894///
895/// ### Example
896/// ```ignore
897/// use sea_orm::entity::prelude::*;
898///
899///  // Use [DeriveEntity] to derive the EntityTrait automatically
900/// #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
901/// pub struct Entity;
902///
903/// /// The [EntityName] describes the name of a table
904/// impl EntityName for Entity {
905///     fn table_name(&self) -> &'static str {
906///         "cake"
907///     }
908/// }
909///
910/// // Derive the ActiveModel
911/// #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
912/// pub struct Model {
913///     pub id: i32,
914///     pub name: String,
915/// }
916///
917/// impl ActiveModelBehavior for ActiveModel {}
918/// ```
919/// See module level docs [crate::entity] for a full example
920#[allow(unused_variables)]
921pub trait ActiveModelBehavior: ActiveModelTrait {
922    /// Create a new ActiveModel with default values. This is also called by `Default::default()`.
923    ///
924    /// You can override it like the following:
925    ///
926    /// ```ignore
927    /// fn new() -> Self {
928    ///     Self {
929    ///         status: Set(Status::New),
930    ///         ..ActiveModelTrait::default()
931    ///     }
932    /// }
933    /// ```
934    fn new() -> Self {
935        <Self as ActiveModelTrait>::default()
936    }
937
938    /// Will be called before `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
939    fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
940    where
941        C: ConnectionTrait,
942    {
943        Ok(self)
944    }
945
946    /// Will be called after `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
947    fn after_save<C>(
948        model: <Self::Entity as EntityTrait>::Model,
949        db: &C,
950        insert: bool,
951    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
952    where
953        C: ConnectionTrait,
954    {
955        Ok(model)
956    }
957
958    /// Will be called before `ActiveModel::delete`
959    fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
960    where
961        C: ConnectionTrait,
962    {
963        Ok(self)
964    }
965
966    /// Will be called after `ActiveModel::delete`
967    fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
968    where
969        C: ConnectionTrait,
970    {
971        Ok(self)
972    }
973}
974
975/// A Trait for any type that can be converted into an ActiveModel
976pub trait IntoActiveModel<A>
977where
978    A: ActiveModelTrait,
979{
980    /// Method to call to perform the conversion
981    fn into_active_model(self) -> A;
982}
983
984impl<A> IntoActiveModel<A> for A
985where
986    A: ActiveModelTrait,
987{
988    fn into_active_model(self) -> A {
989        self
990    }
991}
992
993fn establish_links<EM, J, RM, C>(
994    model: &EM,
995    related_models: &[RM],
996    left: RelationDef,
997    right: RelationDef,
998    delete_leftover: bool,
999    db: &C,
1000) -> Result<(), DbErr>
1001where
1002    EM: ActiveModelTrait,
1003    RM: ActiveModelTrait,
1004    J: EntityTrait,
1005    J::Model: IntoActiveModel<J::ActiveModel>,
1006    J::ActiveModel: ActiveModelBehavior,
1007    C: ConnectionTrait,
1008{
1009    let mut require_leftover = true;
1010
1011    if related_models.is_empty() {
1012        // if there are no related models, then there is no risk of insert conflict
1013        require_leftover = false;
1014    }
1015
1016    let primary_key = J::primary_key_identity();
1017    if require_leftover
1018        && primary_key.fully_contains(&left.from_col)
1019        && primary_key.fully_contains(&right.from_col)
1020    {
1021        // if the primary key is a composite key of the two relations
1022        // we can use on conflict no action safely
1023        require_leftover = false;
1024    }
1025
1026    let mut leftover = Vec::new();
1027    if delete_leftover || require_leftover {
1028        for item in
1029            <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(&left, model)?.all(db)?
1030        {
1031            let item = item.into_active_model();
1032            let key = get_key_from_active_model(&right.from_col, &item)?;
1033            leftover.push((item, key));
1034        }
1035    }
1036    let leftover = leftover; // un-mut
1037
1038    let mut via_models = Vec::new();
1039    let mut all_keys = std::collections::HashSet::new();
1040
1041    for related_model in related_models {
1042        let mut via: J::ActiveModel = ActiveModelBehavior::new();
1043        via.set_parent_key_for_def(model, &left)?;
1044        via.set_parent_key_for_def(related_model, &right)?;
1045        let via_key = get_key_from_active_model(&right.from_col, &via)?;
1046        if !leftover.iter().any(|t| t.1 == via_key) {
1047            // if not already exist, save for insert
1048            via_models.push(via);
1049        }
1050        if delete_leftover {
1051            all_keys.insert(via_key);
1052        }
1053    }
1054
1055    if delete_leftover {
1056        let mut to_delete = Vec::new();
1057        for (leftover, key) in leftover {
1058            if !all_keys.contains(&key) {
1059                to_delete.push(
1060                    leftover
1061                        .get_primary_key_value()
1062                        .expect("item is a full model"),
1063                );
1064            }
1065        }
1066        if !to_delete.is_empty() {
1067            J::delete_many()
1068                .filter_by_value_tuples(&to_delete)
1069                .exec(db)?;
1070        }
1071    }
1072
1073    if !via_models.is_empty() {
1074        // insert new junctions
1075        J::insert_many(via_models)
1076            .on_conflict_do_nothing()
1077            .exec(db)?;
1078    }
1079
1080    Ok(())
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085    use crate::{DbErr, entity::*, tests_cfg::*};
1086    use pretty_assertions::assert_eq;
1087
1088    #[cfg(feature = "with-json")]
1089    use serde_json::json;
1090
1091    #[test]
1092    #[cfg(feature = "macros")]
1093    fn test_derive_into_active_model_1() {
1094        mod my_fruit {
1095            pub use super::fruit::*;
1096            use crate as sea_orm;
1097            use crate::entity::prelude::*;
1098
1099            #[derive(DeriveIntoActiveModel)]
1100            pub struct NewFruit {
1101                // id is omitted
1102                pub name: String,
1103                // it is required as opposed to optional in Model
1104                pub cake_id: i32,
1105            }
1106        }
1107
1108        assert_eq!(
1109            my_fruit::NewFruit {
1110                name: "Apple".to_owned(),
1111                cake_id: 1,
1112            }
1113            .into_active_model(),
1114            fruit::ActiveModel {
1115                id: NotSet,
1116                name: Set("Apple".to_owned()),
1117                cake_id: Set(Some(1)),
1118            }
1119        );
1120    }
1121
1122    #[test]
1123    #[cfg(feature = "macros")]
1124    fn test_derive_into_active_model_2() {
1125        use crate as sea_orm;
1126        use crate::entity::prelude::*;
1127
1128        #[derive(DeriveIntoActiveModel)]
1129        #[sea_orm(active_model = "fruit::ActiveModel")]
1130        struct RequiredFruitName {
1131            name: String,
1132        }
1133
1134        assert_eq!(
1135            RequiredFruitName {
1136                name: "Apple Pie".to_owned(),
1137            }
1138            .into_active_model(),
1139            fruit::ActiveModel {
1140                id: NotSet,
1141                name: Set("Apple Pie".to_owned()),
1142                cake_id: NotSet,
1143            }
1144        );
1145
1146        #[derive(DeriveIntoActiveModel)]
1147        #[sea_orm(active_model = "fruit::ActiveModel")]
1148        struct OptionalFruitName {
1149            name: Option<String>,
1150        }
1151
1152        assert_eq!(
1153            OptionalFruitName {
1154                name: Some("Apple Pie".to_owned()),
1155            }
1156            .into_active_model(),
1157            fruit::ActiveModel {
1158                id: NotSet,
1159                name: Set("Apple Pie".to_owned()),
1160                cake_id: NotSet,
1161            }
1162        );
1163
1164        assert_eq!(
1165            OptionalFruitName { name: None }.into_active_model(),
1166            fruit::ActiveModel {
1167                id: NotSet,
1168                name: NotSet,
1169                cake_id: NotSet,
1170            }
1171        );
1172
1173        #[derive(DeriveIntoActiveModel)]
1174        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1175        struct RequiredAndNotNullFruitCake {
1176            cake_id: i32,
1177        }
1178
1179        assert_eq!(
1180            RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1181            fruit::ActiveModel {
1182                id: NotSet,
1183                name: NotSet,
1184                cake_id: Set(Some(1)),
1185            }
1186        );
1187
1188        #[derive(DeriveIntoActiveModel)]
1189        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1190        struct OptionalAndNotNullFruitCake {
1191            cake_id: Option<i32>,
1192        }
1193
1194        assert_eq!(
1195            OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1196            fruit::ActiveModel {
1197                id: NotSet,
1198                name: NotSet,
1199                cake_id: Set(Some(1)),
1200            }
1201        );
1202
1203        assert_eq!(
1204            OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1205            fruit::ActiveModel {
1206                id: NotSet,
1207                name: NotSet,
1208                cake_id: NotSet,
1209            }
1210        );
1211
1212        #[derive(DeriveIntoActiveModel)]
1213        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1214        struct OptionalAndNullableFruitCake {
1215            cake_id: Option<Option<i32>>,
1216        }
1217
1218        assert_eq!(
1219            OptionalAndNullableFruitCake {
1220                cake_id: Some(Some(1)),
1221            }
1222            .into_active_model(),
1223            fruit::ActiveModel {
1224                id: NotSet,
1225                name: NotSet,
1226                cake_id: Set(Some(1)),
1227            }
1228        );
1229
1230        assert_eq!(
1231            OptionalAndNullableFruitCake {
1232                cake_id: Some(None),
1233            }
1234            .into_active_model(),
1235            fruit::ActiveModel {
1236                id: NotSet,
1237                name: NotSet,
1238                cake_id: Set(None),
1239            }
1240        );
1241
1242        assert_eq!(
1243            OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1244            fruit::ActiveModel {
1245                id: NotSet,
1246                name: NotSet,
1247                cake_id: NotSet,
1248            }
1249        );
1250    }
1251
1252    #[test]
1253    #[cfg(feature = "macros")]
1254    fn test_derive_try_into_model_1() {
1255        mod my_fruit {
1256            use crate as sea_orm;
1257            use crate::entity::prelude::*;
1258
1259            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1260            #[sea_orm(table_name = "fruit")]
1261            pub struct Model {
1262                #[sea_orm(primary_key)]
1263                pub id: i32,
1264                pub name: String,
1265                pub cake_id: Option<i32>,
1266            }
1267
1268            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1269            pub enum Relation {}
1270
1271            impl ActiveModelBehavior for ActiveModel {}
1272        }
1273        assert_eq!(
1274            my_fruit::ActiveModel {
1275                id: Set(1),
1276                name: Set("Pineapple".to_owned()),
1277                cake_id: Set(None),
1278            }
1279            .try_into_model()
1280            .unwrap(),
1281            my_fruit::Model {
1282                id: 1,
1283                name: "Pineapple".to_owned(),
1284                cake_id: None,
1285            }
1286        );
1287
1288        assert_eq!(
1289            my_fruit::ActiveModel {
1290                id: Set(2),
1291                name: Set("Apple".to_owned()),
1292                cake_id: Set(Some(1)),
1293            }
1294            .try_into_model()
1295            .unwrap(),
1296            my_fruit::Model {
1297                id: 2,
1298                name: "Apple".to_owned(),
1299                cake_id: Some(1),
1300            }
1301        );
1302
1303        assert_eq!(
1304            my_fruit::ActiveModel {
1305                id: Set(1),
1306                name: NotSet,
1307                cake_id: Set(None),
1308            }
1309            .try_into_model(),
1310            Err(DbErr::AttrNotSet(String::from("name")))
1311        );
1312
1313        assert_eq!(
1314            my_fruit::ActiveModel {
1315                id: Set(1),
1316                name: Set("Pineapple".to_owned()),
1317                cake_id: NotSet,
1318            }
1319            .try_into_model(),
1320            Err(DbErr::AttrNotSet(String::from("cake_id")))
1321        );
1322    }
1323
1324    #[test]
1325    #[cfg(feature = "macros")]
1326    fn test_derive_try_into_model_2() {
1327        mod my_fruit {
1328            use crate as sea_orm;
1329            use crate::entity::prelude::*;
1330
1331            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1332            #[sea_orm(table_name = "fruit")]
1333            pub struct Model {
1334                #[sea_orm(primary_key)]
1335                pub id: i32,
1336                pub name: String,
1337                #[sea_orm(ignore)]
1338                pub cake_id: Option<i32>,
1339            }
1340
1341            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1342            pub enum Relation {}
1343
1344            impl ActiveModelBehavior for ActiveModel {}
1345        }
1346        assert_eq!(
1347            my_fruit::ActiveModel {
1348                id: Set(1),
1349                name: Set("Pineapple".to_owned()),
1350            }
1351            .try_into_model()
1352            .unwrap(),
1353            my_fruit::Model {
1354                id: 1,
1355                name: "Pineapple".to_owned(),
1356                cake_id: None,
1357            }
1358        );
1359    }
1360
1361    #[test]
1362    #[cfg(feature = "macros")]
1363    fn test_derive_try_into_model_3() {
1364        mod my_fruit {
1365            use crate as sea_orm;
1366            use crate::entity::prelude::*;
1367
1368            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1369            #[sea_orm(table_name = "fruit")]
1370            pub struct Model {
1371                #[sea_orm(primary_key)]
1372                pub id: i32,
1373                #[sea_orm(ignore)]
1374                pub name: String,
1375                pub cake_id: Option<i32>,
1376            }
1377
1378            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1379            pub enum Relation {}
1380
1381            impl ActiveModelBehavior for ActiveModel {}
1382        }
1383        assert_eq!(
1384            my_fruit::ActiveModel {
1385                id: Set(1),
1386                cake_id: Set(Some(1)),
1387            }
1388            .try_into_model()
1389            .unwrap(),
1390            my_fruit::Model {
1391                id: 1,
1392                name: "".to_owned(),
1393                cake_id: Some(1),
1394            }
1395        );
1396    }
1397
1398    #[test]
1399    #[cfg(feature = "with-json")]
1400    fn test_active_model_set_from_json_1() {
1401        assert_eq!(
1402            cake::ActiveModel::from_json(json!({
1403                "id": 1,
1404                "name": "Apple Pie",
1405            }))
1406            .unwrap(),
1407            cake::ActiveModel {
1408                id: Set(1),
1409                name: Set("Apple Pie".to_owned()),
1410            }
1411        );
1412
1413        assert_eq!(
1414            cake::ActiveModel::from_json(json!({
1415                "id": 1,
1416            }))
1417            .unwrap(),
1418            cake::ActiveModel {
1419                id: Set(1),
1420                name: NotSet,
1421            }
1422        );
1423
1424        assert_eq!(
1425            cake::ActiveModel::from_json(json!({
1426                "name": "Apple Pie",
1427            }))
1428            .unwrap(),
1429            cake::ActiveModel {
1430                id: NotSet,
1431                name: Set("Apple Pie".to_owned()),
1432            }
1433        );
1434
1435        let mut cake: cake::ActiveModel = Default::default();
1436        cake.set_from_json(json!({
1437            "name": "Apple Pie",
1438        }))
1439        .unwrap();
1440        assert_eq!(
1441            cake,
1442            cake::ActiveModel {
1443                id: NotSet,
1444                name: Set("Apple Pie".to_owned()),
1445            }
1446        );
1447    }
1448
1449    #[test]
1450    #[cfg(feature = "with-json")]
1451    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1452        let mut fruit: fruit::ActiveModel = Default::default();
1453
1454        fruit.set_from_json(json!({
1455            "name": "Apple",
1456        }))?;
1457        assert_eq!(
1458            fruit,
1459            fruit::ActiveModel {
1460                id: ActiveValue::NotSet,
1461                name: ActiveValue::Set("Apple".to_owned()),
1462                cake_id: ActiveValue::NotSet,
1463            }
1464        );
1465
1466        assert_eq!(
1467            fruit::ActiveModel::from_json(json!({
1468                "name": "Apple",
1469            }))?,
1470            fruit::ActiveModel {
1471                id: ActiveValue::NotSet,
1472                name: ActiveValue::Set("Apple".to_owned()),
1473                cake_id: ActiveValue::NotSet,
1474            }
1475        );
1476
1477        fruit.set_from_json(json!({
1478            "name": "Apple",
1479            "cake_id": null,
1480        }))?;
1481        assert_eq!(
1482            fruit,
1483            fruit::ActiveModel {
1484                id: ActiveValue::NotSet,
1485                name: ActiveValue::Set("Apple".to_owned()),
1486                cake_id: ActiveValue::Set(None),
1487            }
1488        );
1489
1490        fruit.set_from_json(json!({
1491            "id": null,
1492            "name": "Apple",
1493            "cake_id": 1,
1494        }))?;
1495        assert_eq!(
1496            fruit,
1497            fruit::ActiveModel {
1498                id: ActiveValue::NotSet,
1499                name: ActiveValue::Set("Apple".to_owned()),
1500                cake_id: ActiveValue::Set(Some(1)),
1501            }
1502        );
1503
1504        fruit.set_from_json(json!({
1505            "id": 2,
1506            "name": "Apple",
1507            "cake_id": 1,
1508        }))?;
1509        assert_eq!(
1510            fruit,
1511            fruit::ActiveModel {
1512                id: ActiveValue::NotSet,
1513                name: ActiveValue::Set("Apple".to_owned()),
1514                cake_id: ActiveValue::Set(Some(1)),
1515            }
1516        );
1517
1518        let mut fruit = fruit::ActiveModel {
1519            id: ActiveValue::Set(1),
1520            name: ActiveValue::NotSet,
1521            cake_id: ActiveValue::NotSet,
1522        };
1523        fruit.set_from_json(json!({
1524            "id": 8,
1525            "name": "Apple",
1526            "cake_id": 1,
1527        }))?;
1528        assert_eq!(
1529            fruit,
1530            fruit::ActiveModel {
1531                id: ActiveValue::Set(1),
1532                name: ActiveValue::Set("Apple".to_owned()),
1533                cake_id: ActiveValue::Set(Some(1)),
1534            }
1535        );
1536
1537        Ok(())
1538    }
1539
1540    #[test]
1541    #[cfg(feature = "with-json")]
1542    fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1543        use crate::*;
1544
1545        let db = MockDatabase::new(DbBackend::Postgres)
1546            .append_exec_results([
1547                MockExecResult {
1548                    last_insert_id: 1,
1549                    rows_affected: 1,
1550                },
1551                MockExecResult {
1552                    last_insert_id: 1,
1553                    rows_affected: 1,
1554                },
1555            ])
1556            .append_query_results([
1557                [fruit::Model {
1558                    id: 1,
1559                    name: "Apple".to_owned(),
1560                    cake_id: None,
1561                }],
1562                [fruit::Model {
1563                    id: 2,
1564                    name: "Orange".to_owned(),
1565                    cake_id: Some(1),
1566                }],
1567            ])
1568            .into_connection();
1569
1570        let mut fruit: fruit::ActiveModel = Default::default();
1571        fruit.set_from_json(json!({
1572            "name": "Apple",
1573        }))?;
1574        fruit.save(&db)?;
1575
1576        let mut fruit = fruit::ActiveModel {
1577            id: Set(2),
1578            ..Default::default()
1579        };
1580        fruit.set_from_json(json!({
1581            "id": 9,
1582            "name": "Orange",
1583            "cake_id": 1,
1584        }))?;
1585        fruit.save(&db)?;
1586
1587        assert_eq!(
1588            db.into_transaction_log(),
1589            [
1590                Transaction::from_sql_and_values(
1591                    DbBackend::Postgres,
1592                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1593                    ["Apple".into()],
1594                ),
1595                Transaction::from_sql_and_values(
1596                    DbBackend::Postgres,
1597                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1598                    ["Orange".into(), 1i32.into(), 2i32.into()],
1599                ),
1600            ]
1601        );
1602
1603        Ok(())
1604    }
1605
1606    #[test]
1607    fn test_active_model_is_changed() {
1608        let mut fruit: fruit::ActiveModel = Default::default();
1609        assert!(!fruit.is_changed());
1610
1611        fruit.set(fruit::Column::Name, "apple".into());
1612        assert!(fruit.is_changed());
1613
1614        let mut fruit = fruit::Model {
1615            id: 1,
1616            name: "".into(),
1617            cake_id: None,
1618        };
1619        fruit.set("name".parse().unwrap(), "orange".into());
1620        assert_eq!(fruit.name, "orange");
1621    }
1622
1623    #[test]
1624    fn test_reset_1() {
1625        assert_eq!(
1626            fruit::Model {
1627                id: 1,
1628                name: "Apple".into(),
1629                cake_id: None,
1630            }
1631            .into_active_model(),
1632            fruit::ActiveModel {
1633                id: Unchanged(1),
1634                name: Unchanged("Apple".into()),
1635                cake_id: Unchanged(None)
1636            },
1637        );
1638
1639        assert_eq!(
1640            fruit::Model {
1641                id: 1,
1642                name: "Apple".into(),
1643                cake_id: None,
1644            }
1645            .into_active_model()
1646            .reset_all(),
1647            fruit::ActiveModel {
1648                id: Set(1),
1649                name: Set("Apple".into()),
1650                cake_id: Set(None)
1651            },
1652        );
1653
1654        assert_eq!(
1655            fruit::Model {
1656                id: 1,
1657                name: "Apple".into(),
1658                cake_id: Some(2),
1659            }
1660            .into_active_model(),
1661            fruit::ActiveModel {
1662                id: Unchanged(1),
1663                name: Unchanged("Apple".into()),
1664                cake_id: Unchanged(Some(2)),
1665            },
1666        );
1667
1668        assert_eq!(
1669            fruit::Model {
1670                id: 1,
1671                name: "Apple".into(),
1672                cake_id: Some(2),
1673            }
1674            .into_active_model()
1675            .reset_all(),
1676            fruit::ActiveModel {
1677                id: Set(1),
1678                name: Set("Apple".into()),
1679                cake_id: Set(Some(2)),
1680            },
1681        );
1682    }
1683
1684    #[test]
1685    fn test_reset_2() -> Result<(), DbErr> {
1686        use crate::*;
1687
1688        let db = MockDatabase::new(DbBackend::Postgres)
1689            .append_exec_results(vec![
1690                MockExecResult {
1691                    last_insert_id: 1,
1692                    rows_affected: 1,
1693                },
1694                MockExecResult {
1695                    last_insert_id: 1,
1696                    rows_affected: 1,
1697                },
1698            ])
1699            .append_query_results(vec![
1700                vec![fruit::Model {
1701                    id: 1,
1702                    name: "Apple".to_owned(),
1703                    cake_id: None,
1704                }],
1705                vec![fruit::Model {
1706                    id: 1,
1707                    name: "Apple".to_owned(),
1708                    cake_id: None,
1709                }],
1710            ])
1711            .into_connection();
1712
1713        fruit::Model {
1714            id: 1,
1715            name: "Apple".into(),
1716            cake_id: None,
1717        }
1718        .into_active_model()
1719        .update(&db)?;
1720
1721        fruit::Model {
1722            id: 1,
1723            name: "Apple".into(),
1724            cake_id: None,
1725        }
1726        .into_active_model()
1727        .reset_all()
1728        .update(&db)?;
1729
1730        assert_eq!(
1731            db.into_transaction_log(),
1732            vec![
1733                Transaction::from_sql_and_values(
1734                    DbBackend::Postgres,
1735                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1736                    vec![1i32.into(), 1u64.into()],
1737                ),
1738                Transaction::from_sql_and_values(
1739                    DbBackend::Postgres,
1740                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1741                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1742                ),
1743            ]
1744        );
1745
1746        Ok(())
1747    }
1748
1749    #[test]
1750    fn test_active_model_default_values() {
1751        assert_eq!(
1752            fruit::ActiveModel::default_values(),
1753            fruit::ActiveModel {
1754                id: Set(0),
1755                name: Set("".into()),
1756                cake_id: Set(None),
1757            },
1758        );
1759
1760        assert_eq!(
1761            lunch_set::ActiveModel::default_values(),
1762            lunch_set::ActiveModel {
1763                id: Set(0),
1764                name: Set("".into()),
1765                tea: NotSet,
1766            },
1767        );
1768    }
1769
1770    #[test]
1771    fn test_active_model_set_parent_key() {
1772        let mut fruit = fruit::Model {
1773            id: 2,
1774            name: "F".into(),
1775            cake_id: None,
1776        }
1777        .into_active_model();
1778
1779        let cake = cake::Model {
1780            id: 4,
1781            name: "C".into(),
1782        }
1783        .into_active_model();
1784
1785        fruit.set_parent_key(&cake).unwrap();
1786
1787        assert_eq!(
1788            fruit,
1789            fruit::ActiveModel {
1790                id: Unchanged(2),
1791                name: Unchanged("F".into()),
1792                cake_id: Set(Some(4)),
1793            }
1794        );
1795
1796        assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1797
1798        assert_eq!(
1799            fruit,
1800            fruit::ActiveModel {
1801                id: Unchanged(2),
1802                name: Unchanged("F".into()),
1803                cake_id: Set(None),
1804            }
1805        );
1806
1807        let mut cake_filling = cake_filling::ActiveModel::new();
1808
1809        cake_filling.set_parent_key(&cake).unwrap();
1810
1811        assert_eq!(
1812            cake_filling,
1813            cake_filling::ActiveModel {
1814                cake_id: Set(4),
1815                filling_id: NotSet,
1816            }
1817        );
1818    }
1819}