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    /// Create a Vec of ActiveModels from an Arrow RecordBatch.
524    ///
525    /// Each row in the RecordBatch becomes one ActiveModel.
526    /// Columns are matched by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
527    /// Columns present in the RecordBatch are marked as `Set`;
528    /// columns absent from the RecordBatch are marked as `NotSet`.
529    ///
530    /// Supported column types: integers (i8–i64, u8–u64), floats (f32, f64),
531    /// `String`/`Text`, `Boolean`, and date/time types (with `with-chrono` or `with-time`).
532    /// Null values in nullable columns are handled.
533    ///
534    /// When both `with-chrono` and `with-time` features are enabled, chrono values
535    /// are attempted first. If the model uses time-crate types, the conversion
536    /// automatically falls back to the time-crate representation.
537    #[cfg(feature = "with-arrow")]
538    fn from_arrow(batch: &sea_orm_arrow::arrow::array::RecordBatch) -> Result<Vec<Self>, DbErr> {
539        use crate::{IdenStatic, Iterable, with_arrow::arrow_array_to_value};
540
541        let num_rows = batch.num_rows();
542        let mut results = Vec::with_capacity(num_rows);
543
544        for row in 0..num_rows {
545            let mut am = Self::default();
546
547            for col in <<Self::Entity as EntityTrait>::Column>::iter() {
548                let col_name = col.as_str();
549
550                if let Some(arrow_col) = batch.column_by_name(col_name) {
551                    let col_def = col.def();
552                    let col_type = col_def.get_column_type();
553                    let value = arrow_array_to_value(arrow_col.as_ref(), col_type, row)?;
554
555                    // When both chrono and time features are enabled, the primary
556                    // conversion produces chrono Values for date/time columns.
557                    // If the model's field uses time-crate types, try_set will fail;
558                    // retry with the time-crate alternative.
559                    #[cfg(all(feature = "with-chrono", feature = "with-time"))]
560                    {
561                        use crate::with_arrow::{arrow_array_to_value_alt, is_datetime_column};
562                        match am.try_set(col, value) {
563                            Ok(()) => {}
564                            Err(first_err) if is_datetime_column(col_type) => {
565                                if let Some(alt_value) =
566                                    arrow_array_to_value_alt(arrow_col.as_ref(), col_type, row)?
567                                {
568                                    am.try_set(col, alt_value)?;
569                                } else {
570                                    return Err(first_err);
571                                }
572                            }
573                            Err(e) => return Err(e),
574                        }
575                    }
576
577                    #[cfg(not(all(feature = "with-chrono", feature = "with-time")))]
578                    am.try_set(col, value)?;
579                } else {
580                    am.not_set(col);
581                }
582            }
583
584            results.push(am);
585        }
586
587        Ok(results)
588    }
589
590    /// Convert a slice of ActiveModels into an Arrow [`RecordBatch`](arrow::array::RecordBatch).
591    ///
592    /// The `schema` determines the output columns: each schema field is matched
593    /// to an entity column by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
594    /// Columns marked `Set` or `Unchanged` contribute their value;
595    /// `NotSet` columns become null in the output.
596    ///
597    /// Typical usage together with [`ArrowSchema`](crate::ArrowSchema):
598    /// ```ignore
599    /// let schema = MyEntity::arrow_schema();
600    /// let batch = MyActiveModel::to_arrow(&models, &schema)?;
601    /// ```
602    #[cfg(feature = "with-arrow")]
603    fn to_arrow(
604        models: &[Self],
605        schema: &sea_orm_arrow::arrow::datatypes::Schema,
606    ) -> Result<sea_orm_arrow::arrow::array::RecordBatch, DbErr> {
607        use crate::{Iterable, with_arrow::option_values_to_arrow_array};
608        use std::sync::Arc;
609
610        let mut columns: Vec<Arc<dyn sea_orm_arrow::arrow::array::Array>> =
611            Vec::with_capacity(schema.fields().len());
612
613        for field in schema.fields() {
614            let field_name = field.name();
615
616            // Find the entity column whose name matches this schema field
617            let entity_col =
618                <<Self::Entity as EntityTrait>::Column>::iter().find(|c| c.as_str() == field_name);
619
620            if let Some(col) = entity_col {
621                let values: Vec<Option<Value>> = models
622                    .iter()
623                    .map(|m| match m.get(col) {
624                        ActiveValue::Set(v) | ActiveValue::Unchanged(v) => Some(v),
625                        ActiveValue::NotSet => None,
626                    })
627                    .collect();
628
629                let array = option_values_to_arrow_array(&values, field.data_type())?;
630                columns.push(array);
631            } else {
632                // Field in schema but not in entity → null column
633                let array =
634                    sea_orm_arrow::arrow::array::new_null_array(field.data_type(), models.len());
635                columns.push(array);
636            }
637        }
638
639        sea_orm_arrow::arrow::array::RecordBatch::try_new(Arc::new(schema.clone()), columns)
640            .map_err(|e| DbErr::Type(format!("Failed to create RecordBatch: {e}")))
641    }
642
643    /// Return `true` if any attribute of `ActiveModel` is `Set`
644    fn is_changed(&self) -> bool {
645        <Self::Entity as EntityTrait>::Column::iter()
646            .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
647    }
648
649    #[doc(hidden)]
650    /// Set the key to parent's key value for a belongs to relation.
651    fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
652    where
653        R: EntityTrait,
654        AM: ActiveModelTrait<Entity = R>,
655        Self::Entity: Related<R>,
656    {
657        let rel_def = Self::Entity::to();
658
659        if rel_def.is_owner {
660            return Err(DbErr::Type(format!(
661                "Relation from {} to {} is not belongs_to",
662                <Self::Entity as Default>::default().as_str(),
663                <R as Default>::default().as_str()
664            )));
665        }
666
667        let values = get_key_from_active_model(&rel_def.to_col, model)?;
668
669        set_key_on_active_model(&rel_def.from_col, self, values)?;
670
671        Ok(())
672    }
673
674    #[doc(hidden)]
675    fn set_parent_key_for<R, AM>(
676        &mut self,
677        model: &AM,
678        rel: <Self::Entity as EntityTrait>::Relation,
679    ) -> Result<(), DbErr>
680    where
681        R: EntityTrait,
682        AM: ActiveModelTrait<Entity = R>,
683    {
684        let rel_def = rel.def();
685
686        if rel_def.is_owner {
687            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
688        }
689
690        let values = get_key_from_active_model(&rel_def.to_col, model)?;
691
692        set_key_on_active_model(&rel_def.from_col, self, values)?;
693
694        Ok(())
695    }
696
697    #[doc(hidden)]
698    fn set_parent_key_for_def<R, AM>(
699        &mut self,
700        model: &AM,
701        rel_def: &RelationDef,
702    ) -> Result<(), DbErr>
703    where
704        R: EntityTrait,
705        AM: ActiveModelTrait<Entity = R>,
706    {
707        if rel_def.is_owner {
708            return Err(DbErr::Type(format!(
709                "Relation {rel_def:?} is not belongs_to"
710            )));
711        }
712
713        let values = get_key_from_active_model(&rel_def.to_col, model)?;
714
715        set_key_on_active_model(&rel_def.from_col, self, values)?;
716
717        Ok(())
718    }
719
720    #[doc(hidden)]
721    fn set_parent_key_for_self_rev<AM>(
722        &mut self,
723        model: &AM,
724        rel: <Self::Entity as EntityTrait>::Relation,
725    ) -> Result<(), DbErr>
726    where
727        AM: ActiveModelTrait<Entity = Self::Entity>,
728    {
729        let rel_def = rel.def();
730
731        if !rel_def.is_owner {
732            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
733        }
734
735        let values = get_key_from_active_model(&rel_def.from_col, model)?;
736
737        set_key_on_active_model(&rel_def.to_col, self, values)?;
738
739        Ok(())
740    }
741
742    #[doc(hidden)]
743    /// Clear parent association if the relation is optional and return true
744    fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
745    where
746        R: EntityTrait,
747        Self::Entity: Related<R>,
748    {
749        let rel_def = Self::Entity::to();
750
751        if rel_def.is_owner {
752            return Err(DbErr::Type(format!(
753                "Relation from {} to {} is not belongs_to",
754                <Self::Entity as Default>::default().as_str(),
755                <R as Default>::default().as_str()
756            )));
757        }
758
759        clear_key_on_active_model(&rel_def.from_col, self)
760    }
761
762    #[doc(hidden)]
763    fn clear_parent_key_for_self_rev(
764        &mut self,
765        rel: <Self::Entity as EntityTrait>::Relation,
766    ) -> Result<bool, DbErr> {
767        let rel_def = rel.def();
768
769        if !rel_def.is_owner {
770            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
771        }
772
773        clear_key_on_active_model(&rel_def.to_col, self)
774    }
775
776    #[doc(hidden)]
777    /// Get the key value of belongs to relation
778    fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
779    where
780        R: EntityTrait,
781        Self::Entity: Related<R>,
782    {
783        let rel_def = Self::Entity::to();
784
785        if rel_def.is_owner {
786            return Err(DbErr::Type(format!(
787                "Relation from {} to {} is not belongs_to",
788                <Self::Entity as Default>::default().as_str(),
789                <R as Default>::default().as_str()
790            )));
791        }
792
793        get_key_from_active_model(&rel_def.from_col, self)
794    }
795
796    #[doc(hidden)]
797    /// Get the key value of belongs to relation
798    fn get_parent_key_for(
799        &self,
800        rel: <Self::Entity as EntityTrait>::Relation,
801    ) -> Result<ValueTuple, DbErr> {
802        let rel_def = rel.def();
803
804        if rel_def.is_owner {
805            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
806        }
807
808        get_key_from_active_model(&rel_def.from_col, self)
809    }
810
811    #[doc(hidden)]
812    fn find_belongs_to_self(
813        &self,
814        rel: <Self::Entity as EntityTrait>::Relation,
815        db_backend: DbBackend,
816    ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
817        let rel_def = rel.def();
818
819        if !rel_def.is_owner {
820            return Err(DbErr::Type(format!(
821                "Relation {rel:?} is not has_one / has_many"
822            )));
823        }
824
825        let id = get_key_from_active_model(&rel_def.from_col, self)?;
826
827        Ok(Self::Entity::find().filter(
828            column_tuple_in_condition(
829                &<Self::Entity as Default>::default().table_ref(),
830                &rel_def.to_col,
831                &[id],
832                db_backend,
833            )
834            .expect(""),
835        ))
836    }
837
838    #[doc(hidden)]
839    fn find_belongs_to_model<AM>(
840        rel_def: &RelationDef,
841        belongs_to: &AM,
842        db_backend: DbBackend,
843    ) -> Result<crate::query::Select<Self::Entity>, DbErr>
844    where
845        AM: ActiveModelTrait,
846    {
847        if rel_def.is_owner {
848            return Err(DbErr::Type(format!(
849                "Relation {rel_def:?} is not belongs_to"
850            )));
851        }
852
853        let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
854        Ok(<Self::Entity as EntityTrait>::find().filter(
855            column_tuple_in_condition(&rel_def.from_tbl, &rel_def.from_col, &[id], db_backend)
856                .expect(""),
857        ))
858    }
859
860    /// Find related Models belonging to self
861    fn find_related<R>(&self, _: R) -> crate::query::Select<R>
862    where
863        R: EntityTrait,
864        Self::Entity: Related<R>,
865    {
866        Self::Entity::find_related().belongs_to_active_model(self)
867    }
868
869    /// Like find_related, but infer type from `AM`
870    #[doc(hidden)]
871    fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
872    where
873        AM: ActiveModelTrait,
874        Self::Entity: Related<AM::Entity>,
875    {
876        self.find_related(AM::Entity::default())
877    }
878
879    /// Establish links between self and a related Entity for a many-to-many relation.
880    /// New associations will be added, and leftovers can be optionally deleted.
881    #[doc(hidden)]
882    fn establish_links<J, R, RM, C>(
883        &self,
884        _: J,
885        related_models: &[RM],
886        delete_leftover: bool,
887        db: &C,
888    ) -> Result<(), DbErr>
889    where
890        R: EntityTrait,
891        RM: ActiveModelTrait<Entity = R>,
892        J: EntityTrait + Related<R> + Related<Self::Entity>,
893        J::Model: IntoActiveModel<J::ActiveModel>,
894        J::ActiveModel: ActiveModelBehavior,
895        C: ConnectionTrait,
896    {
897        let left = <J as Related<Self::Entity>>::to();
898        let right = <J as Related<R>>::to();
899
900        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
901    }
902
903    /// Establish links for self-referencing many-to-many relation
904    #[doc(hidden)]
905    fn establish_links_self<J, RM, C>(
906        &self,
907        _: J,
908        related_models: &[RM],
909        delete_leftover: bool,
910        db: &C,
911    ) -> Result<(), DbErr>
912    where
913        RM: ActiveModelTrait<Entity = Self::Entity>,
914        J: EntityTrait,
915        J::Model: IntoActiveModel<J::ActiveModel>,
916        J::ActiveModel: ActiveModelBehavior,
917        C: ConnectionTrait,
918        Self::Entity: RelatedSelfVia<J>,
919    {
920        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
921        let right = <Self::Entity as RelatedSelfVia<J>>::to();
922
923        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
924    }
925
926    /// Establish links for self-referencing many-to-many relation, but left-right reversed
927    #[doc(hidden)]
928    fn establish_links_self_rev<J, RM, C>(
929        &self,
930        _: J,
931        related_models: &[RM],
932        delete_leftover: bool,
933        db: &C,
934    ) -> Result<(), DbErr>
935    where
936        RM: ActiveModelTrait<Entity = Self::Entity>,
937        J: EntityTrait,
938        J::Model: IntoActiveModel<J::ActiveModel>,
939        J::ActiveModel: ActiveModelBehavior,
940        C: ConnectionTrait,
941        Self::Entity: RelatedSelfVia<J>,
942    {
943        let left = <Self::Entity as RelatedSelfVia<J>>::to();
944        let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
945
946        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
947    }
948
949    /// Inverse of establish link, break links between two many-to-many models
950    #[doc(hidden)]
951    fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
952    where
953        J: EntityTrait + Related<Self::Entity>,
954        C: ConnectionTrait,
955    {
956        let rel_def = <J as Related<Self::Entity>>::to();
957        let id = get_key_from_active_model(&rel_def.to_col, self)?;
958
959        J::delete_many()
960            .filter(
961                column_tuple_in_condition(
962                    &rel_def.from_tbl,
963                    &rel_def.from_col,
964                    &[id],
965                    db.get_database_backend(),
966                )
967                .expect(""),
968            )
969            .exec(db)
970    }
971
972    /// Like `delete_links` but for self-referencing relations
973    #[doc(hidden)]
974    fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
975    where
976        J: EntityTrait,
977        C: ConnectionTrait,
978        Self::Entity: RelatedSelfVia<J>,
979    {
980        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
981        let right = <Self::Entity as RelatedSelfVia<J>>::to();
982
983        let id = get_key_from_active_model(&left.to_col, self)?;
984
985        if left.to_col != right.to_col {
986            return Err(DbErr::Type("Expect Self Referencing Relation".into()));
987        }
988
989        J::delete_many()
990            .filter(
991                Condition::any()
992                    .add(
993                        column_tuple_in_condition(
994                            &left.from_tbl,
995                            &left.from_col,
996                            std::slice::from_ref(&id),
997                            db.get_database_backend(),
998                        )
999                        .expect(""),
1000                    )
1001                    .add(
1002                        column_tuple_in_condition(
1003                            &right.from_tbl,
1004                            &right.from_col,
1005                            std::slice::from_ref(&id),
1006                            db.get_database_backend(),
1007                        )
1008                        .expect(""),
1009                    ),
1010            )
1011            .exec(db)
1012    }
1013}
1014
1015/// A Trait for overriding the ActiveModel behavior
1016///
1017/// ### Example
1018/// ```ignore
1019/// use sea_orm::entity::prelude::*;
1020///
1021///  // Use [DeriveEntity] to derive the EntityTrait automatically
1022/// #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
1023/// pub struct Entity;
1024///
1025/// /// The [EntityName] describes the name of a table
1026/// impl EntityName for Entity {
1027///     fn table_name(&self) -> &'static str {
1028///         "cake"
1029///     }
1030/// }
1031///
1032/// // Derive the ActiveModel
1033/// #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
1034/// pub struct Model {
1035///     pub id: i32,
1036///     pub name: String,
1037/// }
1038///
1039/// impl ActiveModelBehavior for ActiveModel {}
1040/// ```
1041/// See module level docs [crate::entity] for a full example
1042#[allow(unused_variables)]
1043pub trait ActiveModelBehavior: ActiveModelTrait {
1044    /// Create a new ActiveModel with default values. This is also called by `Default::default()`.
1045    ///
1046    /// You can override it like the following:
1047    ///
1048    /// ```ignore
1049    /// fn new() -> Self {
1050    ///     Self {
1051    ///         status: Set(Status::New),
1052    ///         ..ActiveModelTrait::default()
1053    ///     }
1054    /// }
1055    /// ```
1056    fn new() -> Self {
1057        <Self as ActiveModelTrait>::default()
1058    }
1059
1060    /// Will be called before `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
1061    fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1062    where
1063        C: ConnectionTrait,
1064    {
1065        Ok(self)
1066    }
1067
1068    /// Will be called after `ActiveModel::insert`, `ActiveModel::update`, and `ActiveModel::save`
1069    fn after_save<C>(
1070        model: <Self::Entity as EntityTrait>::Model,
1071        db: &C,
1072        insert: bool,
1073    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1074    where
1075        C: ConnectionTrait,
1076    {
1077        Ok(model)
1078    }
1079
1080    /// Will be called before `ActiveModel::delete`
1081    fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1082    where
1083        C: ConnectionTrait,
1084    {
1085        Ok(self)
1086    }
1087
1088    /// Will be called after `ActiveModel::delete`
1089    fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1090    where
1091        C: ConnectionTrait,
1092    {
1093        Ok(self)
1094    }
1095}
1096
1097/// A Trait for any type that can be converted into an ActiveModel
1098pub trait IntoActiveModel<A>
1099where
1100    A: ActiveModelTrait,
1101{
1102    /// Method to call to perform the conversion
1103    fn into_active_model(self) -> A;
1104}
1105
1106impl<A> IntoActiveModel<A> for A
1107where
1108    A: ActiveModelTrait,
1109{
1110    fn into_active_model(self) -> A {
1111        self
1112    }
1113}
1114
1115fn establish_links<EM, J, RM, C>(
1116    model: &EM,
1117    related_models: &[RM],
1118    left: RelationDef,
1119    right: RelationDef,
1120    delete_leftover: bool,
1121    db: &C,
1122) -> Result<(), DbErr>
1123where
1124    EM: ActiveModelTrait,
1125    RM: ActiveModelTrait,
1126    J: EntityTrait,
1127    J::Model: IntoActiveModel<J::ActiveModel>,
1128    J::ActiveModel: ActiveModelBehavior,
1129    C: ConnectionTrait,
1130{
1131    let mut require_leftover = true;
1132
1133    if related_models.is_empty() {
1134        // if there are no related models, then there is no risk of insert conflict
1135        require_leftover = false;
1136    }
1137
1138    let primary_key = J::primary_key_identity();
1139    if require_leftover
1140        && primary_key.fully_contains(&left.from_col)
1141        && primary_key.fully_contains(&right.from_col)
1142    {
1143        // if the primary key is a composite key of the two relations
1144        // we can use on conflict no action safely
1145        require_leftover = false;
1146    }
1147
1148    let mut leftover = Vec::new();
1149    if delete_leftover || require_leftover {
1150        for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1151            &left,
1152            model,
1153            db.get_database_backend(),
1154        )?
1155        .all(db)?
1156        {
1157            let item = item.into_active_model();
1158            let key = get_key_from_active_model(&right.from_col, &item)?;
1159            leftover.push((item, key));
1160        }
1161    }
1162    let leftover = leftover; // un-mut
1163
1164    let mut via_models = Vec::new();
1165    let mut all_keys = std::collections::HashSet::new();
1166
1167    for related_model in related_models {
1168        let mut via: J::ActiveModel = ActiveModelBehavior::new();
1169        via.set_parent_key_for_def(model, &left)?;
1170        via.set_parent_key_for_def(related_model, &right)?;
1171        let via_key = get_key_from_active_model(&right.from_col, &via)?;
1172        if !leftover.iter().any(|t| t.1 == via_key) {
1173            // if not already exist, save for insert
1174            via_models.push(via);
1175        }
1176        if delete_leftover {
1177            all_keys.insert(via_key);
1178        }
1179    }
1180
1181    if delete_leftover {
1182        let mut to_delete = Vec::new();
1183        for (leftover, key) in leftover {
1184            if !all_keys.contains(&key) {
1185                to_delete.push(
1186                    leftover
1187                        .get_primary_key_value()
1188                        .expect("item is a full model"),
1189                );
1190            }
1191        }
1192        if !to_delete.is_empty() {
1193            J::delete_many()
1194                .filter_by_value_tuples(&to_delete, db.get_database_backend())
1195                .exec(db)?;
1196        }
1197    }
1198
1199    if !via_models.is_empty() {
1200        // insert new junctions
1201        J::insert_many(via_models)
1202            .on_conflict_do_nothing()
1203            .exec(db)?;
1204    }
1205
1206    Ok(())
1207}
1208
1209#[cfg(test)]
1210mod tests {
1211    use crate::{DbErr, entity::*, tests_cfg::*};
1212    use pretty_assertions::assert_eq;
1213
1214    #[cfg(feature = "with-json")]
1215    use serde_json::json;
1216
1217    #[test]
1218    #[cfg(feature = "macros")]
1219    fn test_derive_into_active_model_1() {
1220        mod my_fruit {
1221            pub use super::fruit::*;
1222            use crate as sea_orm;
1223            use crate::entity::prelude::*;
1224
1225            #[derive(DeriveIntoActiveModel)]
1226            pub struct NewFruit {
1227                // id is omitted
1228                pub name: String,
1229                // it is required as opposed to optional in Model
1230                pub cake_id: i32,
1231            }
1232        }
1233
1234        assert_eq!(
1235            my_fruit::NewFruit {
1236                name: "Apple".to_owned(),
1237                cake_id: 1,
1238            }
1239            .into_active_model(),
1240            fruit::ActiveModel {
1241                id: NotSet,
1242                name: Set("Apple".to_owned()),
1243                cake_id: Set(Some(1)),
1244            }
1245        );
1246    }
1247
1248    #[test]
1249    #[cfg(feature = "macros")]
1250    fn test_derive_into_active_model_2() {
1251        use crate as sea_orm;
1252        use crate::entity::prelude::*;
1253
1254        #[derive(DeriveIntoActiveModel)]
1255        #[sea_orm(active_model = "fruit::ActiveModel")]
1256        struct RequiredFruitName {
1257            name: String,
1258        }
1259
1260        assert_eq!(
1261            RequiredFruitName {
1262                name: "Apple Pie".to_owned(),
1263            }
1264            .into_active_model(),
1265            fruit::ActiveModel {
1266                id: NotSet,
1267                name: Set("Apple Pie".to_owned()),
1268                cake_id: NotSet,
1269            }
1270        );
1271
1272        #[derive(DeriveIntoActiveModel)]
1273        #[sea_orm(active_model = "fruit::ActiveModel")]
1274        struct OptionalFruitName {
1275            name: Option<String>,
1276        }
1277
1278        assert_eq!(
1279            OptionalFruitName {
1280                name: Some("Apple Pie".to_owned()),
1281            }
1282            .into_active_model(),
1283            fruit::ActiveModel {
1284                id: NotSet,
1285                name: Set("Apple Pie".to_owned()),
1286                cake_id: NotSet,
1287            }
1288        );
1289
1290        assert_eq!(
1291            OptionalFruitName { name: None }.into_active_model(),
1292            fruit::ActiveModel {
1293                id: NotSet,
1294                name: NotSet,
1295                cake_id: NotSet,
1296            }
1297        );
1298
1299        #[derive(DeriveIntoActiveModel)]
1300        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1301        struct RequiredAndNotNullFruitCake {
1302            cake_id: i32,
1303        }
1304
1305        assert_eq!(
1306            RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1307            fruit::ActiveModel {
1308                id: NotSet,
1309                name: NotSet,
1310                cake_id: Set(Some(1)),
1311            }
1312        );
1313
1314        #[derive(DeriveIntoActiveModel)]
1315        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1316        struct OptionalAndNotNullFruitCake {
1317            cake_id: Option<i32>,
1318        }
1319
1320        assert_eq!(
1321            OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1322            fruit::ActiveModel {
1323                id: NotSet,
1324                name: NotSet,
1325                cake_id: Set(Some(1)),
1326            }
1327        );
1328
1329        assert_eq!(
1330            OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1331            fruit::ActiveModel {
1332                id: NotSet,
1333                name: NotSet,
1334                cake_id: NotSet,
1335            }
1336        );
1337
1338        #[derive(DeriveIntoActiveModel)]
1339        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1340        struct OptionalAndNullableFruitCake {
1341            cake_id: Option<Option<i32>>,
1342        }
1343
1344        assert_eq!(
1345            OptionalAndNullableFruitCake {
1346                cake_id: Some(Some(1)),
1347            }
1348            .into_active_model(),
1349            fruit::ActiveModel {
1350                id: NotSet,
1351                name: NotSet,
1352                cake_id: Set(Some(1)),
1353            }
1354        );
1355
1356        assert_eq!(
1357            OptionalAndNullableFruitCake {
1358                cake_id: Some(None),
1359            }
1360            .into_active_model(),
1361            fruit::ActiveModel {
1362                id: NotSet,
1363                name: NotSet,
1364                cake_id: Set(None),
1365            }
1366        );
1367
1368        assert_eq!(
1369            OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1370            fruit::ActiveModel {
1371                id: NotSet,
1372                name: NotSet,
1373                cake_id: NotSet,
1374            }
1375        );
1376    }
1377
1378    #[test]
1379    #[cfg(feature = "macros")]
1380    fn test_derive_try_into_model_1() {
1381        mod my_fruit {
1382            use crate as sea_orm;
1383            use crate::entity::prelude::*;
1384
1385            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1386            #[sea_orm(table_name = "fruit")]
1387            pub struct Model {
1388                #[sea_orm(primary_key)]
1389                pub id: i32,
1390                pub name: String,
1391                pub cake_id: Option<i32>,
1392            }
1393
1394            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1395            pub enum Relation {}
1396
1397            impl ActiveModelBehavior for ActiveModel {}
1398        }
1399        assert_eq!(
1400            my_fruit::ActiveModel {
1401                id: Set(1),
1402                name: Set("Pineapple".to_owned()),
1403                cake_id: Set(None),
1404            }
1405            .try_into_model()
1406            .unwrap(),
1407            my_fruit::Model {
1408                id: 1,
1409                name: "Pineapple".to_owned(),
1410                cake_id: None,
1411            }
1412        );
1413
1414        assert_eq!(
1415            my_fruit::ActiveModel {
1416                id: Set(2),
1417                name: Set("Apple".to_owned()),
1418                cake_id: Set(Some(1)),
1419            }
1420            .try_into_model()
1421            .unwrap(),
1422            my_fruit::Model {
1423                id: 2,
1424                name: "Apple".to_owned(),
1425                cake_id: Some(1),
1426            }
1427        );
1428
1429        assert_eq!(
1430            my_fruit::ActiveModel {
1431                id: Set(1),
1432                name: NotSet,
1433                cake_id: Set(None),
1434            }
1435            .try_into_model(),
1436            Err(DbErr::AttrNotSet(String::from("name")))
1437        );
1438
1439        assert_eq!(
1440            my_fruit::ActiveModel {
1441                id: Set(1),
1442                name: Set("Pineapple".to_owned()),
1443                cake_id: NotSet,
1444            }
1445            .try_into_model(),
1446            Err(DbErr::AttrNotSet(String::from("cake_id")))
1447        );
1448    }
1449
1450    #[test]
1451    #[cfg(feature = "macros")]
1452    fn test_derive_try_into_model_2() {
1453        mod my_fruit {
1454            use crate as sea_orm;
1455            use crate::entity::prelude::*;
1456
1457            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1458            #[sea_orm(table_name = "fruit")]
1459            pub struct Model {
1460                #[sea_orm(primary_key)]
1461                pub id: i32,
1462                pub name: String,
1463                #[sea_orm(ignore)]
1464                pub cake_id: Option<i32>,
1465            }
1466
1467            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1468            pub enum Relation {}
1469
1470            impl ActiveModelBehavior for ActiveModel {}
1471        }
1472        assert_eq!(
1473            my_fruit::ActiveModel {
1474                id: Set(1),
1475                name: Set("Pineapple".to_owned()),
1476            }
1477            .try_into_model()
1478            .unwrap(),
1479            my_fruit::Model {
1480                id: 1,
1481                name: "Pineapple".to_owned(),
1482                cake_id: None,
1483            }
1484        );
1485    }
1486
1487    #[test]
1488    #[cfg(feature = "macros")]
1489    fn test_derive_try_into_model_3() {
1490        mod my_fruit {
1491            use crate as sea_orm;
1492            use crate::entity::prelude::*;
1493
1494            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1495            #[sea_orm(table_name = "fruit")]
1496            pub struct Model {
1497                #[sea_orm(primary_key)]
1498                pub id: i32,
1499                #[sea_orm(ignore)]
1500                pub name: String,
1501                pub cake_id: Option<i32>,
1502            }
1503
1504            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1505            pub enum Relation {}
1506
1507            impl ActiveModelBehavior for ActiveModel {}
1508        }
1509        assert_eq!(
1510            my_fruit::ActiveModel {
1511                id: Set(1),
1512                cake_id: Set(Some(1)),
1513            }
1514            .try_into_model()
1515            .unwrap(),
1516            my_fruit::Model {
1517                id: 1,
1518                name: "".to_owned(),
1519                cake_id: Some(1),
1520            }
1521        );
1522    }
1523
1524    #[test]
1525    #[cfg(feature = "with-json")]
1526    fn test_active_model_set_from_json_1() {
1527        assert_eq!(
1528            cake::ActiveModel::from_json(json!({
1529                "id": 1,
1530                "name": "Apple Pie",
1531            }))
1532            .unwrap(),
1533            cake::ActiveModel {
1534                id: Set(1),
1535                name: Set("Apple Pie".to_owned()),
1536            }
1537        );
1538
1539        assert_eq!(
1540            cake::ActiveModel::from_json(json!({
1541                "id": 1,
1542            }))
1543            .unwrap(),
1544            cake::ActiveModel {
1545                id: Set(1),
1546                name: NotSet,
1547            }
1548        );
1549
1550        assert_eq!(
1551            cake::ActiveModel::from_json(json!({
1552                "name": "Apple Pie",
1553            }))
1554            .unwrap(),
1555            cake::ActiveModel {
1556                id: NotSet,
1557                name: Set("Apple Pie".to_owned()),
1558            }
1559        );
1560
1561        let mut cake: cake::ActiveModel = Default::default();
1562        cake.set_from_json(json!({
1563            "name": "Apple Pie",
1564        }))
1565        .unwrap();
1566        assert_eq!(
1567            cake,
1568            cake::ActiveModel {
1569                id: NotSet,
1570                name: Set("Apple Pie".to_owned()),
1571            }
1572        );
1573    }
1574
1575    #[test]
1576    #[cfg(feature = "with-json")]
1577    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
1578        let mut fruit: fruit::ActiveModel = Default::default();
1579
1580        fruit.set_from_json(json!({
1581            "name": "Apple",
1582        }))?;
1583        assert_eq!(
1584            fruit,
1585            fruit::ActiveModel {
1586                id: ActiveValue::NotSet,
1587                name: ActiveValue::Set("Apple".to_owned()),
1588                cake_id: ActiveValue::NotSet,
1589            }
1590        );
1591
1592        assert_eq!(
1593            fruit::ActiveModel::from_json(json!({
1594                "name": "Apple",
1595            }))?,
1596            fruit::ActiveModel {
1597                id: ActiveValue::NotSet,
1598                name: ActiveValue::Set("Apple".to_owned()),
1599                cake_id: ActiveValue::NotSet,
1600            }
1601        );
1602
1603        fruit.set_from_json(json!({
1604            "name": "Apple",
1605            "cake_id": null,
1606        }))?;
1607        assert_eq!(
1608            fruit,
1609            fruit::ActiveModel {
1610                id: ActiveValue::NotSet,
1611                name: ActiveValue::Set("Apple".to_owned()),
1612                cake_id: ActiveValue::Set(None),
1613            }
1614        );
1615
1616        fruit.set_from_json(json!({
1617            "id": null,
1618            "name": "Apple",
1619            "cake_id": 1,
1620        }))?;
1621        assert_eq!(
1622            fruit,
1623            fruit::ActiveModel {
1624                id: ActiveValue::NotSet,
1625                name: ActiveValue::Set("Apple".to_owned()),
1626                cake_id: ActiveValue::Set(Some(1)),
1627            }
1628        );
1629
1630        fruit.set_from_json(json!({
1631            "id": 2,
1632            "name": "Apple",
1633            "cake_id": 1,
1634        }))?;
1635        assert_eq!(
1636            fruit,
1637            fruit::ActiveModel {
1638                id: ActiveValue::NotSet,
1639                name: ActiveValue::Set("Apple".to_owned()),
1640                cake_id: ActiveValue::Set(Some(1)),
1641            }
1642        );
1643
1644        let mut fruit = fruit::ActiveModel {
1645            id: ActiveValue::Set(1),
1646            name: ActiveValue::NotSet,
1647            cake_id: ActiveValue::NotSet,
1648        };
1649        fruit.set_from_json(json!({
1650            "id": 8,
1651            "name": "Apple",
1652            "cake_id": 1,
1653        }))?;
1654        assert_eq!(
1655            fruit,
1656            fruit::ActiveModel {
1657                id: ActiveValue::Set(1),
1658                name: ActiveValue::Set("Apple".to_owned()),
1659                cake_id: ActiveValue::Set(Some(1)),
1660            }
1661        );
1662
1663        Ok(())
1664    }
1665
1666    #[test]
1667    #[cfg(feature = "with-json")]
1668    fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
1669        use crate::*;
1670
1671        let db = MockDatabase::new(DbBackend::Postgres)
1672            .append_exec_results([
1673                MockExecResult {
1674                    last_insert_id: 1,
1675                    rows_affected: 1,
1676                },
1677                MockExecResult {
1678                    last_insert_id: 1,
1679                    rows_affected: 1,
1680                },
1681            ])
1682            .append_query_results([
1683                [fruit::Model {
1684                    id: 1,
1685                    name: "Apple".to_owned(),
1686                    cake_id: None,
1687                }],
1688                [fruit::Model {
1689                    id: 2,
1690                    name: "Orange".to_owned(),
1691                    cake_id: Some(1),
1692                }],
1693            ])
1694            .into_connection();
1695
1696        let mut fruit: fruit::ActiveModel = Default::default();
1697        fruit.set_from_json(json!({
1698            "name": "Apple",
1699        }))?;
1700        fruit.save(&db)?;
1701
1702        let mut fruit = fruit::ActiveModel {
1703            id: Set(2),
1704            ..Default::default()
1705        };
1706        fruit.set_from_json(json!({
1707            "id": 9,
1708            "name": "Orange",
1709            "cake_id": 1,
1710        }))?;
1711        fruit.save(&db)?;
1712
1713        assert_eq!(
1714            db.into_transaction_log(),
1715            [
1716                Transaction::from_sql_and_values(
1717                    DbBackend::Postgres,
1718                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
1719                    ["Apple".into()],
1720                ),
1721                Transaction::from_sql_and_values(
1722                    DbBackend::Postgres,
1723                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1724                    ["Orange".into(), 1i32.into(), 2i32.into()],
1725                ),
1726            ]
1727        );
1728
1729        Ok(())
1730    }
1731
1732    #[test]
1733    fn test_active_model_is_changed() {
1734        let mut fruit: fruit::ActiveModel = Default::default();
1735        assert!(!fruit.is_changed());
1736
1737        fruit.set(fruit::Column::Name, "apple".into());
1738        assert!(fruit.is_changed());
1739
1740        let mut fruit = fruit::Model {
1741            id: 1,
1742            name: "".into(),
1743            cake_id: None,
1744        };
1745        fruit.set("name".parse().unwrap(), "orange".into());
1746        assert_eq!(fruit.name, "orange");
1747    }
1748
1749    #[test]
1750    fn test_reset_1() {
1751        assert_eq!(
1752            fruit::Model {
1753                id: 1,
1754                name: "Apple".into(),
1755                cake_id: None,
1756            }
1757            .into_active_model(),
1758            fruit::ActiveModel {
1759                id: Unchanged(1),
1760                name: Unchanged("Apple".into()),
1761                cake_id: Unchanged(None)
1762            },
1763        );
1764
1765        assert_eq!(
1766            fruit::Model {
1767                id: 1,
1768                name: "Apple".into(),
1769                cake_id: None,
1770            }
1771            .into_active_model()
1772            .reset_all(),
1773            fruit::ActiveModel {
1774                id: Set(1),
1775                name: Set("Apple".into()),
1776                cake_id: Set(None)
1777            },
1778        );
1779
1780        assert_eq!(
1781            fruit::Model {
1782                id: 1,
1783                name: "Apple".into(),
1784                cake_id: Some(2),
1785            }
1786            .into_active_model(),
1787            fruit::ActiveModel {
1788                id: Unchanged(1),
1789                name: Unchanged("Apple".into()),
1790                cake_id: Unchanged(Some(2)),
1791            },
1792        );
1793
1794        assert_eq!(
1795            fruit::Model {
1796                id: 1,
1797                name: "Apple".into(),
1798                cake_id: Some(2),
1799            }
1800            .into_active_model()
1801            .reset_all(),
1802            fruit::ActiveModel {
1803                id: Set(1),
1804                name: Set("Apple".into()),
1805                cake_id: Set(Some(2)),
1806            },
1807        );
1808    }
1809
1810    #[test]
1811    fn test_reset_2() -> Result<(), DbErr> {
1812        use crate::*;
1813
1814        let db = MockDatabase::new(DbBackend::Postgres)
1815            .append_exec_results(vec![
1816                MockExecResult {
1817                    last_insert_id: 1,
1818                    rows_affected: 1,
1819                },
1820                MockExecResult {
1821                    last_insert_id: 1,
1822                    rows_affected: 1,
1823                },
1824            ])
1825            .append_query_results(vec![
1826                vec![fruit::Model {
1827                    id: 1,
1828                    name: "Apple".to_owned(),
1829                    cake_id: None,
1830                }],
1831                vec![fruit::Model {
1832                    id: 1,
1833                    name: "Apple".to_owned(),
1834                    cake_id: None,
1835                }],
1836            ])
1837            .into_connection();
1838
1839        fruit::Model {
1840            id: 1,
1841            name: "Apple".into(),
1842            cake_id: None,
1843        }
1844        .into_active_model()
1845        .update(&db)?;
1846
1847        fruit::Model {
1848            id: 1,
1849            name: "Apple".into(),
1850            cake_id: None,
1851        }
1852        .into_active_model()
1853        .reset_all()
1854        .update(&db)?;
1855
1856        assert_eq!(
1857            db.into_transaction_log(),
1858            vec![
1859                Transaction::from_sql_and_values(
1860                    DbBackend::Postgres,
1861                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
1862                    vec![1i32.into(), 1u64.into()],
1863                ),
1864                Transaction::from_sql_and_values(
1865                    DbBackend::Postgres,
1866                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
1867                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
1868                ),
1869            ]
1870        );
1871
1872        Ok(())
1873    }
1874
1875    #[test]
1876    fn test_active_model_default_values() {
1877        assert_eq!(
1878            fruit::ActiveModel::default_values(),
1879            fruit::ActiveModel {
1880                id: Set(0),
1881                name: Set("".into()),
1882                cake_id: Set(None),
1883            },
1884        );
1885
1886        assert_eq!(
1887            lunch_set::ActiveModel::default_values(),
1888            lunch_set::ActiveModel {
1889                id: Set(0),
1890                name: Set("".into()),
1891                tea: NotSet,
1892            },
1893        );
1894    }
1895
1896    #[test]
1897    fn test_active_model_set_parent_key() {
1898        let mut fruit = fruit::Model {
1899            id: 2,
1900            name: "F".into(),
1901            cake_id: None,
1902        }
1903        .into_active_model();
1904
1905        let cake = cake::Model {
1906            id: 4,
1907            name: "C".into(),
1908        }
1909        .into_active_model();
1910
1911        fruit.set_parent_key(&cake).unwrap();
1912
1913        assert_eq!(
1914            fruit,
1915            fruit::ActiveModel {
1916                id: Unchanged(2),
1917                name: Unchanged("F".into()),
1918                cake_id: Set(Some(4)),
1919            }
1920        );
1921
1922        assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
1923
1924        assert_eq!(
1925            fruit,
1926            fruit::ActiveModel {
1927                id: Unchanged(2),
1928                name: Unchanged("F".into()),
1929                cake_id: Set(None),
1930            }
1931        );
1932
1933        let mut cake_filling = cake_filling::ActiveModel::new();
1934
1935        cake_filling.set_parent_key(&cake).unwrap();
1936
1937        assert_eq!(
1938            cake_filling,
1939            cake_filling::ActiveModel {
1940                cake_id: Set(4),
1941                filling_id: NotSet,
1942            }
1943        );
1944    }
1945}