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, TryInsertResult, UpdateResult, 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/// The editable counterpart of a [`Model`](crate::ModelTrait), used to build
16/// `INSERT` and `UPDATE` statements.
17///
18/// Each field of an ActiveModel is wrapped in an [`ActiveValue`], so it can
19/// be one of:
20///
21/// - [`Set(v)`](ActiveValue::Set) — a new value to write,
22/// - [`Unchanged(v)`](ActiveValue::Unchanged) — the value already in the
23///   database, will not be sent in `UPDATE`,
24/// - [`NotSet`](ActiveValue::NotSet) — value is absent; the column is
25///   omitted from `INSERT` (letting the database supply a default) and
26///   from `UPDATE`.
27///
28/// This makes ActiveModel ideal for partial updates: only the columns you
29/// touch end up in the generated `UPDATE`.
30pub trait ActiveModelTrait: Clone + Debug {
31    /// The [`EntityTrait`] this ActiveModel belongs to.
32    type Entity: EntityTrait;
33
34    /// Take the [`ActiveValue`] of a column, leaving it as `NotSet`.
35    fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
36
37    /// Read the [`ActiveValue`] of a column.
38    fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
39
40    /// Set one column to `Set(v)`. Panics on type mismatch; prefer
41    /// [`try_set`](Self::try_set) when the value comes from untrusted input.
42    fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
43        self.try_set(c, v)
44            .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
45    }
46
47    /// Set one column to `Set(v)` only if `v` differs from the current value,
48    /// avoiding spurious `UPDATE` rewrites. Panics on type mismatch.
49    fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
50
51    /// Set one column to `Set(v)`, returning an error on type mismatch.
52    fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;
53
54    /// Mark a column as `NotSet` so it is omitted from the next `INSERT` or
55    /// `UPDATE`.
56    fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);
57
58    /// `true` if the column is currently in the `NotSet` state.
59    fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
60
61    /// A fresh ActiveModel with every column `NotSet`.
62    fn default() -> Self;
63
64    /// A fresh ActiveModel pre-populated with `Set(default_value)` for each
65    /// column that has a `Default` impl; other columns remain `NotSet`.
66    fn default_values() -> Self;
67
68    /// Promote one column from [`Unchanged`](ActiveValue::Unchanged) to
69    /// [`Set`](ActiveValue::Set) so it will be included in the next
70    /// `UPDATE`. Leaves [`NotSet`](ActiveValue::NotSet) untouched.
71    fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);
72
73    /// Apply [`reset`](Self::reset) to every column, forcing the next
74    /// `UPDATE` to write all non-`NotSet` columns.
75    fn reset_all(mut self) -> Self {
76        for col in <Self::Entity as EntityTrait>::Column::iter() {
77            self.reset(col);
78        }
79        self
80    }
81
82    /// The primary key as a `ValueTuple`, or `None` if any primary-key
83    /// column is still `NotSet`.
84    fn get_primary_key_value(&self) -> Option<ValueTuple> {
85        let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
86        macro_rules! next {
87            () => {
88                self.get(cols.next()?.into_column()).into_value()?
89            };
90        }
91        match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
92            1 => {
93                let s1 = next!();
94                Some(ValueTuple::One(s1))
95            }
96            2 => {
97                let s1 = next!();
98                let s2 = next!();
99                Some(ValueTuple::Two(s1, s2))
100            }
101            3 => {
102                let s1 = next!();
103                let s2 = next!();
104                let s3 = next!();
105                Some(ValueTuple::Three(s1, s2, s3))
106            }
107            len => {
108                let mut vec = Vec::with_capacity(len);
109                for _ in 0..len {
110                    let s = next!();
111                    vec.push(s);
112                }
113                Some(ValueTuple::Many(vec))
114            }
115        }
116    }
117
118    /// Perform an `INSERT` operation on the ActiveModel
119    ///
120    /// # Example (Postgres)
121    ///
122    /// ```
123    /// # use sea_orm::{error::*, tests_cfg::*, *};
124    /// #
125    /// # #[cfg(feature = "mock")]
126    /// # pub fn main() -> Result<(), DbErr> {
127    /// #
128    /// # let db = MockDatabase::new(DbBackend::Postgres)
129    /// #     .append_query_results([
130    /// #         [cake::Model {
131    /// #             id: 15,
132    /// #             name: "Apple Pie".to_owned(),
133    /// #         }],
134    /// #     ])
135    /// #     .into_connection();
136    /// #
137    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
138    ///
139    /// let apple = cake::ActiveModel {
140    ///     name: Set("Apple Pie".to_owned()),
141    ///     ..Default::default()
142    /// };
143    ///
144    /// assert_eq!(
145    ///     apple.insert(&db)?,
146    ///     cake::Model {
147    ///         id: 15,
148    ///         name: "Apple Pie".to_owned(),
149    ///     }
150    /// );
151    ///
152    /// assert_eq!(
153    ///     db.into_transaction_log(),
154    ///     [Transaction::from_sql_and_values(
155    ///         DbBackend::Postgres,
156    ///         r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id", "name""#,
157    ///         ["Apple Pie".into()]
158    ///     )]
159    /// );
160    /// #
161    /// # Ok(())
162    /// # }
163    /// ```
164    ///
165    /// # Example (MySQL)
166    ///
167    /// ```
168    /// # use sea_orm::{error::*, tests_cfg::*, *};
169    /// #
170    /// # #[cfg(feature = "mock")]
171    /// # pub fn main() -> Result<(), DbErr> {
172    /// #
173    /// # let db = MockDatabase::new(DbBackend::MySql)
174    /// #     .append_query_results([
175    /// #         [cake::Model {
176    /// #             id: 15,
177    /// #             name: "Apple Pie".to_owned(),
178    /// #         }],
179    /// #     ])
180    /// #     .append_exec_results([
181    /// #         MockExecResult {
182    /// #             last_insert_id: 15,
183    /// #             rows_affected: 1,
184    /// #         },
185    /// #     ])
186    /// #     .into_connection();
187    /// #
188    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
189    ///
190    /// let apple = cake::ActiveModel {
191    ///     name: Set("Apple Pie".to_owned()),
192    ///     ..Default::default()
193    /// };
194    ///
195    /// assert_eq!(
196    ///     apple.insert(&db)?,
197    ///     cake::Model {
198    ///         id: 15,
199    ///         name: "Apple Pie".to_owned(),
200    ///     }
201    /// );
202    ///
203    /// assert_eq!(
204    ///     db.into_transaction_log(),
205    ///     [
206    ///         Transaction::from_sql_and_values(
207    ///             DbBackend::MySql,
208    ///             r#"INSERT INTO `cake` (`name`) VALUES (?)"#,
209    ///             ["Apple Pie".into()]
210    ///         ),
211    ///         Transaction::from_sql_and_values(
212    ///             DbBackend::MySql,
213    ///             r#"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = ? LIMIT ?"#,
214    ///             [15.into(), 1u64.into()]
215    ///         )
216    ///     ]
217    /// );
218    /// #
219    /// # Ok(())
220    /// # }
221    /// ```
222    fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
223    where
224        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
225        Self: ActiveModelBehavior,
226        C: ConnectionTrait,
227    {
228        let am = ActiveModelBehavior::before_save(self, db, true)?;
229        let model = <Self::Entity as EntityTrait>::insert(am).exec_with_returning(db)?;
230        Self::after_save(model, db, true)
231    }
232
233    /// Perform the `UPDATE` operation on an ActiveModel
234    ///
235    /// # Example (Postgres)
236    ///
237    /// ```
238    /// # use sea_orm::{error::*, tests_cfg::*, *};
239    /// #
240    /// # #[cfg(feature = "mock")]
241    /// # pub fn main() -> Result<(), DbErr> {
242    /// #
243    /// # let db = MockDatabase::new(DbBackend::Postgres)
244    /// #     .append_query_results([
245    /// #         [fruit::Model {
246    /// #             id: 1,
247    /// #             name: "Orange".to_owned(),
248    /// #             cake_id: None,
249    /// #         }],
250    /// #     ])
251    /// #     .into_connection();
252    /// #
253    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
254    ///
255    /// let orange = fruit::ActiveModel {
256    ///     id: Set(1),
257    ///     name: Set("Orange".to_owned()),
258    ///     ..Default::default()
259    /// };
260    ///
261    /// assert_eq!(
262    ///     orange.update(&db)?,
263    ///     fruit::Model {
264    ///         id: 1,
265    ///         name: "Orange".to_owned(),
266    ///         cake_id: None,
267    ///     }
268    /// );
269    ///
270    /// assert_eq!(
271    ///     db.into_transaction_log(),
272    ///     [Transaction::from_sql_and_values(
273    ///         DbBackend::Postgres,
274    ///         r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2 RETURNING "id", "name", "cake_id""#,
275    ///         ["Orange".into(), 1i32.into()]
276    ///     )]);
277    /// #
278    /// # Ok(())
279    /// # }
280    /// ```
281    ///
282    /// # Example (MySQL)
283    ///
284    /// ```
285    /// # use sea_orm::{error::*, tests_cfg::*, *};
286    /// #
287    /// # #[cfg(feature = "mock")]
288    /// # pub fn main() -> Result<(), DbErr> {
289    /// #
290    /// # let db = MockDatabase::new(DbBackend::MySql)
291    /// #     .append_query_results([
292    /// #         [fruit::Model {
293    /// #             id: 1,
294    /// #             name: "Orange".to_owned(),
295    /// #             cake_id: None,
296    /// #         }],
297    /// #     ])
298    /// #     .append_exec_results([
299    /// #         MockExecResult {
300    /// #             last_insert_id: 0,
301    /// #             rows_affected: 1,
302    /// #         },
303    /// #     ])
304    /// #     .into_connection();
305    /// #
306    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
307    ///
308    /// let orange = fruit::ActiveModel {
309    ///     id: Set(1),
310    ///     name: Set("Orange".to_owned()),
311    ///     ..Default::default()
312    /// };
313    ///
314    /// assert_eq!(
315    ///     orange.update(&db)?,
316    ///     fruit::Model {
317    ///         id: 1,
318    ///         name: "Orange".to_owned(),
319    ///         cake_id: None,
320    ///     }
321    /// );
322    ///
323    /// assert_eq!(
324    ///     db.into_transaction_log(),
325    ///     [
326    ///         Transaction::from_sql_and_values(
327    ///             DbBackend::MySql,
328    ///             r#"UPDATE `fruit` SET `name` = ? WHERE `fruit`.`id` = ?"#,
329    ///             ["Orange".into(), 1i32.into()]
330    ///         ),
331    ///         Transaction::from_sql_and_values(
332    ///             DbBackend::MySql,
333    ///             r#"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = ? LIMIT ?"#,
334    ///             [1i32.into(), 1u64.into()]
335    ///         )]);
336    /// #
337    /// # Ok(())
338    /// # }
339    /// ```
340    fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
341    where
342        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
343        Self: ActiveModelBehavior,
344        C: ConnectionTrait,
345    {
346        let am = ActiveModelBehavior::before_save(self, db, false)?;
347        let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db)?;
348        Self::after_save(model, db, false)
349    }
350
351    /// Update an ActiveModel without a RETURNING clause, yielding an
352    /// [`UpdateResult`] instead of the updated model. Useful on backends without
353    /// RETURNING support, or when the updated model is not needed.
354    ///
355    /// Unlike [`ActiveModelTrait::update`], this runs
356    /// [`ActiveModelBehavior::before_save`] but does **not** run
357    /// [`ActiveModelBehavior::after_save`] (there is no returned model to pass to
358    /// it). Returns [`DbErr::RecordNotUpdated`] if no row matches.
359    fn update_without_returning<'a, C>(self, db: &'a C) -> Result<UpdateResult, DbErr>
360    where
361        Self: ActiveModelBehavior,
362        C: ConnectionTrait,
363    {
364        let am = ActiveModelBehavior::before_save(self, db, false)?;
365        Self::Entity::update(am).exec_without_returning(db)
366    }
367
368    /// Insert the model if primary key is `NotSet`, update otherwise.
369    /// Only works if the entity has auto increment primary key.
370    fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
371    where
372        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
373        Self: ActiveModelBehavior,
374        C: ConnectionTrait,
375    {
376        let res = if !self.is_update() {
377            self.insert(db)
378        } else {
379            self.update(db)
380        }?;
381        Ok(res.into_active_model())
382    }
383
384    /// Returns true if the primary key is fully-specified
385    #[doc(hidden)]
386    fn is_update(&self) -> bool {
387        let mut is_update = true;
388        for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
389            let col = key.into_column();
390            if self.is_not_set(col) {
391                is_update = false;
392                break;
393            }
394        }
395        is_update
396    }
397
398    /// Delete an active model by its primary key
399    ///
400    /// # Example
401    ///
402    /// ```
403    /// # use sea_orm::{error::*, tests_cfg::*, *};
404    /// #
405    /// # #[cfg(feature = "mock")]
406    /// # pub fn main() -> Result<(), DbErr> {
407    /// #
408    /// # let db = MockDatabase::new(DbBackend::Postgres)
409    /// #     .append_exec_results([
410    /// #         MockExecResult {
411    /// #             last_insert_id: 0,
412    /// #             rows_affected: 1,
413    /// #         },
414    /// #     ])
415    /// #     .into_connection();
416    /// #
417    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
418    ///
419    /// let orange = fruit::ActiveModel {
420    ///     id: Set(3),
421    ///     ..Default::default()
422    /// };
423    ///
424    /// let delete_result = orange.delete(&db)?;
425    ///
426    /// assert_eq!(delete_result.rows_affected, 1);
427    ///
428    /// assert_eq!(
429    ///     db.into_transaction_log(),
430    ///     [Transaction::from_sql_and_values(
431    ///         DbBackend::Postgres,
432    ///         r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
433    ///         [3i32.into()]
434    ///     )]
435    /// );
436    /// #
437    /// # Ok(())
438    /// # }
439    /// ```
440    fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
441    where
442        Self: ActiveModelBehavior,
443        C: ConnectionTrait,
444    {
445        let am = ActiveModelBehavior::before_delete(self, db)?;
446        let am_clone = am.clone();
447        let delete_res = Self::Entity::delete(am).exec(db)?;
448        ActiveModelBehavior::after_delete(am_clone, db)?;
449        Ok(delete_res)
450    }
451
452    /// Set the corresponding attributes in the ActiveModel from a JSON value
453    ///
454    /// Note that this method will not alter the primary key values in ActiveModel.
455    #[cfg(feature = "with-json")]
456    fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
457    where
458        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
459        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
460        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
461            serde::de::Deserialize<'de> + serde::Serialize,
462    {
463        use crate::Iterable;
464
465        // Backup primary key values
466        let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
467            <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
468                .map(|pk| (pk.into_column(), self.take(pk.into_column())))
469                .collect();
470
471        // Replace all values in ActiveModel
472        *self = Self::from_json(json)?;
473
474        // Restore primary key values
475        for (col, active_value) in primary_key_values {
476            match active_value {
477                ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
478                NotSet => self.not_set(col),
479            }
480        }
481
482        Ok(())
483    }
484
485    /// Create ActiveModel from a JSON value
486    #[cfg(feature = "with-json")]
487    fn from_json(json: serde_json::Value) -> Result<Self, DbErr>
488    where
489        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
490        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
491        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
492            serde::de::Deserialize<'de> + serde::Serialize,
493    {
494        use crate::{IdenStatic, Iterable};
495
496        let serde_json::Value::Object(mut input) = json else {
497            return Err(DbErr::Json(format!(
498                "invalid type: expected JSON object for {}",
499                <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
500            )));
501        };
502
503        let dummy_am = Self::default_values();
504        let len = <<Self::Entity as EntityTrait>::Column>::iter().len();
505        // Mark down which attribute exists in the JSON object
506        let mut json_keys = Vec::with_capacity(len);
507        let mut merged = serde_json::Map::with_capacity(len);
508
509        for col in <<Self::Entity as EntityTrait>::Column>::iter() {
510            let key = col.json_key();
511            let has_key = input.contains_key(key);
512            json_keys.push((col, has_key));
513            match dummy_am.get(col) {
514                ActiveValue::Unchanged(value) | ActiveValue::Set(value) => {
515                    merged.insert(key.to_owned(), sea_query::sea_value_to_json_value(&value));
516                }
517                _ => {}
518            }
519        }
520
521        merged.append(&mut input);
522        let _ = input;
523
524        let json_value = serde_json::Value::Object(merged);
525
526        // Convert JSON object into ActiveModel via Model
527        let model: <Self::Entity as EntityTrait>::Model =
528            serde_json::from_value(json_value).map_err(json_err)?;
529        let mut am = model.into_active_model();
530
531        // Transform attribute that exists in JSON object into ActiveValue::Set, otherwise ActiveValue::NotSet
532        for (col, json_key_exists) in json_keys {
533            match (json_key_exists, am.get(col)) {
534                (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
535                    am.set(col, value);
536                }
537                _ => {
538                    am.not_set(col);
539                }
540            }
541        }
542
543        Ok(am)
544    }
545
546    /// Create a Vec of ActiveModels from an Arrow RecordBatch.
547    ///
548    /// Each row in the RecordBatch becomes one ActiveModel.
549    /// Columns are matched by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
550    /// Columns present in the RecordBatch are marked as `Set`;
551    /// columns absent from the RecordBatch are marked as `NotSet`.
552    ///
553    /// Supported column types: integers (i8–i64, u8–u64), floats (f32, f64),
554    /// `String`/`Text`, `Boolean`, and date/time types (with `with-chrono` or `with-time`).
555    /// Null values in nullable columns are handled.
556    ///
557    /// When both `with-chrono` and `with-time` features are enabled, chrono values
558    /// are attempted first. If the model uses time-crate types, the conversion
559    /// automatically falls back to the time-crate representation.
560    #[cfg(feature = "with-arrow")]
561    fn from_arrow(batch: &sea_orm_arrow::arrow::array::RecordBatch) -> Result<Vec<Self>, DbErr> {
562        use crate::{IdenStatic, Iterable, with_arrow::arrow_array_to_value};
563
564        let num_rows = batch.num_rows();
565        let mut results = Vec::with_capacity(num_rows);
566
567        for row in 0..num_rows {
568            let mut am = Self::default();
569
570            for col in <<Self::Entity as EntityTrait>::Column>::iter() {
571                let col_name = col.as_str();
572
573                if let Some(arrow_col) = batch.column_by_name(col_name) {
574                    let col_def = col.def();
575                    let col_type = col_def.get_column_type();
576                    let value = arrow_array_to_value(arrow_col.as_ref(), col_type, row)?;
577
578                    // When both chrono and time features are enabled, the primary
579                    // conversion produces chrono Values for date/time columns.
580                    // If the model's field uses time-crate types, try_set will fail;
581                    // retry with the time-crate alternative.
582                    #[cfg(all(feature = "with-chrono", feature = "with-time"))]
583                    {
584                        use crate::with_arrow::{arrow_array_to_value_alt, is_datetime_column};
585                        match am.try_set(col, value) {
586                            Ok(()) => {}
587                            Err(first_err) if is_datetime_column(col_type) => {
588                                if let Some(alt_value) =
589                                    arrow_array_to_value_alt(arrow_col.as_ref(), col_type, row)?
590                                {
591                                    am.try_set(col, alt_value)?;
592                                } else {
593                                    return Err(first_err);
594                                }
595                            }
596                            Err(e) => return Err(e),
597                        }
598                    }
599
600                    #[cfg(not(all(feature = "with-chrono", feature = "with-time")))]
601                    am.try_set(col, value)?;
602                } else {
603                    am.not_set(col);
604                }
605            }
606
607            results.push(am);
608        }
609
610        Ok(results)
611    }
612
613    /// Convert a slice of ActiveModels into an Arrow [`RecordBatch`](arrow::array::RecordBatch).
614    ///
615    /// The `schema` determines the output columns: each schema field is matched
616    /// to an entity column by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
617    /// Columns marked `Set` or `Unchanged` contribute their value;
618    /// `NotSet` columns become null in the output.
619    ///
620    /// Typical usage together with [`ArrowSchema`](crate::ArrowSchema):
621    /// ```ignore
622    /// let schema = MyEntity::arrow_schema();
623    /// let batch = MyActiveModel::to_arrow(&models, &schema)?;
624    /// ```
625    #[cfg(feature = "with-arrow")]
626    fn to_arrow(
627        models: &[Self],
628        schema: &sea_orm_arrow::arrow::datatypes::Schema,
629    ) -> Result<sea_orm_arrow::arrow::array::RecordBatch, DbErr> {
630        use crate::{Iterable, with_arrow::option_values_to_arrow_array};
631        use std::sync::Arc;
632
633        let mut columns: Vec<Arc<dyn sea_orm_arrow::arrow::array::Array>> =
634            Vec::with_capacity(schema.fields().len());
635
636        for field in schema.fields() {
637            let field_name = field.name();
638
639            // Find the entity column whose name matches this schema field
640            let entity_col =
641                <<Self::Entity as EntityTrait>::Column>::iter().find(|c| c.as_str() == field_name);
642
643            if let Some(col) = entity_col {
644                let values: Vec<Option<Value>> = models
645                    .iter()
646                    .map(|m| match m.get(col) {
647                        ActiveValue::Set(v) | ActiveValue::Unchanged(v) => Some(v),
648                        ActiveValue::NotSet => None,
649                    })
650                    .collect();
651
652                let array = option_values_to_arrow_array(&values, field.data_type())?;
653                columns.push(array);
654            } else {
655                // Field in schema but not in entity → null column
656                let array =
657                    sea_orm_arrow::arrow::array::new_null_array(field.data_type(), models.len());
658                columns.push(array);
659            }
660        }
661
662        sea_orm_arrow::arrow::array::RecordBatch::try_new(Arc::new(schema.clone()), columns)
663            .map_err(|e| DbErr::Type(format!("Failed to create RecordBatch: {e}")))
664    }
665
666    /// Return `true` if any attribute of `ActiveModel` is `Set`
667    fn is_changed(&self) -> bool {
668        <Self::Entity as EntityTrait>::Column::iter()
669            .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
670    }
671
672    #[doc(hidden)]
673    /// Set the key to parent's key value for a belongs to relation.
674    fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
675    where
676        R: EntityTrait,
677        AM: ActiveModelTrait<Entity = R>,
678        Self::Entity: Related<R>,
679    {
680        let rel_def = Self::Entity::to();
681
682        if rel_def.is_owner {
683            return Err(DbErr::Type(format!(
684                "Relation from {} to {} is not belongs_to",
685                <Self::Entity as Default>::default().as_str(),
686                <R as Default>::default().as_str()
687            )));
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<R, AM>(
699        &mut self,
700        model: &AM,
701        rel: <Self::Entity as EntityTrait>::Relation,
702    ) -> Result<(), DbErr>
703    where
704        R: EntityTrait,
705        AM: ActiveModelTrait<Entity = R>,
706    {
707        let rel_def = rel.def();
708
709        if rel_def.is_owner {
710            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
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_def<R, AM>(
722        &mut self,
723        model: &AM,
724        rel_def: &RelationDef,
725    ) -> Result<(), DbErr>
726    where
727        R: EntityTrait,
728        AM: ActiveModelTrait<Entity = R>,
729    {
730        if rel_def.is_owner {
731            return Err(DbErr::Type(format!(
732                "Relation {rel_def:?} is not belongs_to"
733            )));
734        }
735
736        let values = get_key_from_active_model(&rel_def.to_col, model)?;
737
738        set_key_on_active_model(&rel_def.from_col, self, values)?;
739
740        Ok(())
741    }
742
743    #[doc(hidden)]
744    fn set_parent_key_for_self_rev<AM>(
745        &mut self,
746        model: &AM,
747        rel: <Self::Entity as EntityTrait>::Relation,
748    ) -> Result<(), DbErr>
749    where
750        AM: ActiveModelTrait<Entity = Self::Entity>,
751    {
752        let rel_def = rel.def();
753
754        if !rel_def.is_owner {
755            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
756        }
757
758        let values = get_key_from_active_model(&rel_def.from_col, model)?;
759
760        set_key_on_active_model(&rel_def.to_col, self, values)?;
761
762        Ok(())
763    }
764
765    #[doc(hidden)]
766    /// Clear parent association if the relation is optional and return true
767    fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
768    where
769        R: EntityTrait,
770        Self::Entity: Related<R>,
771    {
772        let rel_def = Self::Entity::to();
773
774        if rel_def.is_owner {
775            return Err(DbErr::Type(format!(
776                "Relation from {} to {} is not belongs_to",
777                <Self::Entity as Default>::default().as_str(),
778                <R as Default>::default().as_str()
779            )));
780        }
781
782        clear_key_on_active_model(&rel_def.from_col, self)
783    }
784
785    #[doc(hidden)]
786    fn clear_parent_key_for_self_rev(
787        &mut self,
788        rel: <Self::Entity as EntityTrait>::Relation,
789    ) -> Result<bool, DbErr> {
790        let rel_def = rel.def();
791
792        if !rel_def.is_owner {
793            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
794        }
795
796        clear_key_on_active_model(&rel_def.to_col, self)
797    }
798
799    #[doc(hidden)]
800    /// Get the key value of belongs to relation
801    fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
802    where
803        R: EntityTrait,
804        Self::Entity: Related<R>,
805    {
806        let rel_def = Self::Entity::to();
807
808        if rel_def.is_owner {
809            return Err(DbErr::Type(format!(
810                "Relation from {} to {} is not belongs_to",
811                <Self::Entity as Default>::default().as_str(),
812                <R as Default>::default().as_str()
813            )));
814        }
815
816        get_key_from_active_model(&rel_def.from_col, self)
817    }
818
819    #[doc(hidden)]
820    /// Get the key value of belongs to relation
821    fn get_parent_key_for(
822        &self,
823        rel: <Self::Entity as EntityTrait>::Relation,
824    ) -> Result<ValueTuple, DbErr> {
825        let rel_def = rel.def();
826
827        if rel_def.is_owner {
828            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
829        }
830
831        get_key_from_active_model(&rel_def.from_col, self)
832    }
833
834    #[doc(hidden)]
835    fn find_belongs_to_self(
836        &self,
837        rel: <Self::Entity as EntityTrait>::Relation,
838        db_backend: DbBackend,
839    ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
840        let rel_def = rel.def();
841
842        if !rel_def.is_owner {
843            return Err(DbErr::Type(format!(
844                "Relation {rel:?} is not has_one / has_many"
845            )));
846        }
847
848        let id = get_key_from_active_model(&rel_def.from_col, self)?;
849
850        Ok(Self::Entity::find().filter(
851            column_tuple_in_condition(
852                &<Self::Entity as Default>::default().table_ref(),
853                &rel_def.to_col,
854                &[id],
855                db_backend,
856            )
857            .expect(""),
858        ))
859    }
860
861    #[doc(hidden)]
862    fn find_belongs_to_model<AM>(
863        rel_def: &RelationDef,
864        belongs_to: &AM,
865        db_backend: DbBackend,
866    ) -> Result<crate::query::Select<Self::Entity>, DbErr>
867    where
868        AM: ActiveModelTrait,
869    {
870        if rel_def.is_owner {
871            return Err(DbErr::Type(format!(
872                "Relation {rel_def:?} is not belongs_to"
873            )));
874        }
875
876        let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
877        Ok(<Self::Entity as EntityTrait>::find().filter(
878            column_tuple_in_condition(&rel_def.from_tbl, &rel_def.from_col, &[id], db_backend)
879                .expect(""),
880        ))
881    }
882
883    /// Find related Models belonging to self
884    fn find_related<R>(&self, _: R) -> crate::query::Select<R>
885    where
886        R: EntityTrait,
887        Self::Entity: Related<R>,
888    {
889        Self::Entity::find_related().belongs_to_active_model(self)
890    }
891
892    /// Establish links between self and a related Entity for a many-to-many relation.
893    /// New associations will be added, and leftovers can be optionally deleted.
894    #[doc(hidden)]
895    fn establish_links<J, R, RM, C>(
896        &self,
897        _: J,
898        related_models: &[RM],
899        delete_leftover: bool,
900        db: &C,
901    ) -> Result<(), DbErr>
902    where
903        R: EntityTrait,
904        RM: ActiveModelTrait<Entity = R>,
905        J: EntityTrait + Related<R> + Related<Self::Entity>,
906        J::Model: IntoActiveModel<J::ActiveModel>,
907        J::ActiveModel: ActiveModelBehavior,
908        C: ConnectionTrait,
909    {
910        let left = <J as Related<Self::Entity>>::to();
911        let right = <J as Related<R>>::to();
912
913        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
914    }
915
916    /// Establish links for self-referencing many-to-many relation
917    #[doc(hidden)]
918    fn establish_links_self<J, RM, C>(
919        &self,
920        _: J,
921        related_models: &[RM],
922        delete_leftover: bool,
923        db: &C,
924    ) -> Result<(), DbErr>
925    where
926        RM: ActiveModelTrait<Entity = Self::Entity>,
927        J: EntityTrait,
928        J::Model: IntoActiveModel<J::ActiveModel>,
929        J::ActiveModel: ActiveModelBehavior,
930        C: ConnectionTrait,
931        Self::Entity: RelatedSelfVia<J>,
932    {
933        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
934        let right = <Self::Entity as RelatedSelfVia<J>>::to();
935
936        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
937    }
938
939    /// Establish links for self-referencing many-to-many relation, but left-right reversed
940    #[doc(hidden)]
941    fn establish_links_self_rev<J, RM, C>(
942        &self,
943        _: J,
944        related_models: &[RM],
945        delete_leftover: bool,
946        db: &C,
947    ) -> Result<(), DbErr>
948    where
949        RM: ActiveModelTrait<Entity = Self::Entity>,
950        J: EntityTrait,
951        J::Model: IntoActiveModel<J::ActiveModel>,
952        J::ActiveModel: ActiveModelBehavior,
953        C: ConnectionTrait,
954        Self::Entity: RelatedSelfVia<J>,
955    {
956        let left = <Self::Entity as RelatedSelfVia<J>>::to();
957        let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
958
959        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
960    }
961
962    /// Inverse of establish link, break links between two many-to-many models
963    #[doc(hidden)]
964    fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
965    where
966        J: EntityTrait + Related<Self::Entity>,
967        C: ConnectionTrait,
968    {
969        let rel_def = <J as Related<Self::Entity>>::to();
970        let id = get_key_from_active_model(&rel_def.to_col, self)?;
971
972        J::delete_many()
973            .filter(
974                column_tuple_in_condition(
975                    &rel_def.from_tbl,
976                    &rel_def.from_col,
977                    &[id],
978                    db.get_database_backend(),
979                )
980                .expect(""),
981            )
982            .exec(db)
983    }
984
985    /// Like `delete_links` but for self-referencing relations
986    #[doc(hidden)]
987    fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
988    where
989        J: EntityTrait,
990        C: ConnectionTrait,
991        Self::Entity: RelatedSelfVia<J>,
992    {
993        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
994        let right = <Self::Entity as RelatedSelfVia<J>>::to();
995
996        let id = get_key_from_active_model(&left.to_col, self)?;
997
998        if left.to_col != right.to_col {
999            return Err(DbErr::Type("Expect Self Referencing Relation".into()));
1000        }
1001
1002        J::delete_many()
1003            .filter(
1004                Condition::any()
1005                    .add(
1006                        column_tuple_in_condition(
1007                            &left.from_tbl,
1008                            &left.from_col,
1009                            std::slice::from_ref(&id),
1010                            db.get_database_backend(),
1011                        )
1012                        .expect(""),
1013                    )
1014                    .add(
1015                        column_tuple_in_condition(
1016                            &right.from_tbl,
1017                            &right.from_col,
1018                            std::slice::from_ref(&id),
1019                            db.get_database_backend(),
1020                        )
1021                        .expect(""),
1022                    ),
1023            )
1024            .exec(db)
1025    }
1026}
1027
1028/// Lifecycle hooks for an [`ActiveModelTrait`].
1029///
1030/// Every entity must have an impl of this trait — even the empty
1031/// `impl ActiveModelBehavior for ActiveModel {}` you see in the examples is
1032/// required so that the default `new` / `before_save` / `after_save` /
1033/// `before_delete` / `after_delete` implementations are wired up. Override
1034/// the hooks to enforce invariants, populate computed columns, or run side
1035/// effects around saves and deletes.
1036///
1037/// ```ignore
1038/// use sea_orm::entity::prelude::*;
1039///
1040/// impl ActiveModelBehavior for ActiveModel {
1041///     fn before_save<C>(mut self, _db: &C, insert: bool) -> Result<Self, DbErr>
1042///     where
1043///         C: ConnectionTrait,
1044///     {
1045///         if insert && self.created_at.is_not_set() {
1046///             self.created_at = Set(chrono::Utc::now());
1047///         }
1048///         self.updated_at = Set(chrono::Utc::now());
1049///         Ok(self)
1050///     }
1051/// }
1052/// ```
1053#[allow(unused_variables)]
1054pub trait ActiveModelBehavior: ActiveModelTrait {
1055    /// Build a fresh ActiveModel. Defaults to [`ActiveModelTrait::default`]
1056    /// (every column `NotSet`); override to pre-fill columns:
1057    ///
1058    /// ```ignore
1059    /// fn new() -> Self {
1060    ///     Self {
1061    ///         status: Set(Status::New),
1062    ///         ..ActiveModelTrait::default()
1063    ///     }
1064    /// }
1065    /// ```
1066    fn new() -> Self {
1067        <Self as ActiveModelTrait>::default()
1068    }
1069
1070    /// Hook invoked before `insert`, `update`, and `save`. `insert` is `true`
1071    /// for inserts. Return an error to abort the operation.
1072    fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1073    where
1074        C: ConnectionTrait,
1075    {
1076        Ok(self)
1077    }
1078
1079    /// Hook invoked after `insert`, `update`, and `save` succeed. Receives
1080    /// (and may transform) the resulting `Model`.
1081    fn after_save<C>(
1082        model: <Self::Entity as EntityTrait>::Model,
1083        db: &C,
1084        insert: bool,
1085    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1086    where
1087        C: ConnectionTrait,
1088    {
1089        Ok(model)
1090    }
1091
1092    /// Hook invoked before `delete`. Return an error to abort.
1093    fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1094    where
1095        C: ConnectionTrait,
1096    {
1097        Ok(self)
1098    }
1099
1100    /// Hook invoked after `delete` succeeds.
1101    fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1102    where
1103        C: ConnectionTrait,
1104    {
1105        Ok(self)
1106    }
1107}
1108
1109/// A Trait for any type that can be converted into an `ActiveModel`,
1110/// can be derived using `DeriveIntoActiveModel`.
1111///
1112/// ## Derive Macro Example
1113///
1114/// ```rust
1115/// use sea_orm::DeriveIntoActiveModel;
1116/// mod fruit {
1117///     use sea_orm::entity::prelude::*;
1118///     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1119///     #[sea_orm(table_name = "fruit")]
1120///     pub struct Model {
1121///         #[sea_orm(primary_key)]
1122///         pub id: i32,
1123///         pub name: String,
1124///         pub cake_id: Option<i32>,
1125///     }
1126///     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1127///     pub enum Relation {}
1128///     impl ActiveModelBehavior for ActiveModel {}
1129/// }
1130///
1131/// #[derive(DeriveIntoActiveModel)]
1132/// #[sea_orm(active_model = "fruit::ActiveModel")]
1133/// struct NewFruit {
1134///     name: String,
1135///     // `id` and `cake_id` are omitted - they become `NotSet`
1136/// }
1137/// ```
1138///
1139/// ## `set(...)` - always set absent ActiveModel fields
1140///
1141/// ```rust
1142/// # mod fruit {
1143/// #     use sea_orm::entity::prelude::*;
1144/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1145/// #     #[sea_orm(table_name = "fruit")]
1146/// #     pub struct Model {
1147/// #         #[sea_orm(primary_key)]
1148/// #         pub id: i32,
1149/// #         pub name: String,
1150/// #         pub cake_id: Option<i32>,
1151/// #     }
1152/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1153/// #     pub enum Relation {}
1154/// #     impl ActiveModelBehavior for ActiveModel {}
1155/// # }
1156/// use sea_orm::DeriveIntoActiveModel;
1157///
1158/// #[derive(DeriveIntoActiveModel)]
1159/// #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1160/// struct NewFruit {
1161///     name: String,
1162///     // `cake_id` is not on the struct, but will always be `Set(None)`
1163/// }
1164/// ```
1165///
1166/// ## `default = "expr"` - fallback for `Option<T>` struct fields
1167///
1168/// ```rust
1169/// # mod fruit {
1170/// #     use sea_orm::entity::prelude::*;
1171/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1172/// #     #[sea_orm(table_name = "fruit")]
1173/// #     pub struct Model {
1174/// #         #[sea_orm(primary_key)]
1175/// #         pub id: i32,
1176/// #         pub name: String,
1177/// #         pub cake_id: Option<i32>,
1178/// #     }
1179/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1180/// #     pub enum Relation {}
1181/// #     impl ActiveModelBehavior for ActiveModel {}
1182/// # }
1183/// use sea_orm::DeriveIntoActiveModel;
1184///
1185/// #[derive(DeriveIntoActiveModel)]
1186/// #[sea_orm(active_model = "fruit::ActiveModel")]
1187/// struct UpdateFruit {
1188///     /// `Some("Apple")` -> `Set("Apple")`, `None` ->`Set("Unnamed")`
1189///     #[sea_orm(default = "String::from(\"Unnamed\")")]
1190///     name: Option<String>,
1191/// }
1192/// ```
1193pub trait IntoActiveModel<A>
1194where
1195    A: ActiveModelTrait,
1196{
1197    /// Method to call to perform the conversion
1198    fn into_active_model(self) -> A;
1199}
1200
1201impl<A> IntoActiveModel<A> for A
1202where
1203    A: ActiveModelTrait,
1204{
1205    fn into_active_model(self) -> A {
1206        self
1207    }
1208}
1209
1210fn establish_links<EM, J, RM, C>(
1211    model: &EM,
1212    related_models: &[RM],
1213    left: RelationDef,
1214    right: RelationDef,
1215    delete_leftover: bool,
1216    db: &C,
1217) -> Result<(), DbErr>
1218where
1219    EM: ActiveModelTrait,
1220    RM: ActiveModelTrait,
1221    J: EntityTrait,
1222    J::Model: IntoActiveModel<J::ActiveModel>,
1223    J::ActiveModel: ActiveModelBehavior,
1224    C: ConnectionTrait,
1225{
1226    let mut require_leftover = true;
1227
1228    if related_models.is_empty() {
1229        // if there are no related models, then there is no risk of insert conflict
1230        require_leftover = false;
1231    }
1232
1233    let primary_key = J::primary_key_identity();
1234    if require_leftover
1235        && primary_key.fully_contains(&left.from_col)
1236        && primary_key.fully_contains(&right.from_col)
1237    {
1238        // if the primary key is a composite key of the two relations
1239        // we can use on conflict no action safely
1240        require_leftover = false;
1241    }
1242
1243    let mut leftover = Vec::new();
1244    if delete_leftover || require_leftover {
1245        for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1246            &left,
1247            model,
1248            db.get_database_backend(),
1249        )?
1250        .all(db)?
1251        {
1252            let item = item.into_active_model();
1253            let key = get_key_from_active_model(&right.from_col, &item)?;
1254            leftover.push((item, key));
1255        }
1256    }
1257    let leftover = leftover; // un-mut
1258
1259    let mut via_models = Vec::new();
1260    let mut all_keys = std::collections::HashSet::new();
1261
1262    for related_model in related_models {
1263        let mut via: J::ActiveModel = ActiveModelBehavior::new();
1264        via.set_parent_key_for_def(model, &left)?;
1265        via.set_parent_key_for_def(related_model, &right)?;
1266        let via_key = get_key_from_active_model(&right.from_col, &via)?;
1267        if !leftover.iter().any(|t| t.1 == via_key) {
1268            // if not already exist, save for insert
1269            via_models.push(via);
1270        }
1271        if delete_leftover {
1272            all_keys.insert(via_key);
1273        }
1274    }
1275
1276    if delete_leftover {
1277        let mut to_delete = Vec::new();
1278        let mut to_delete_am = Vec::new();
1279        for (leftover, key) in leftover {
1280            if !all_keys.contains(&key) {
1281                to_delete.push(
1282                    leftover
1283                        .get_primary_key_value()
1284                        .expect("item is a full model"),
1285                );
1286                to_delete_am.push(leftover);
1287            }
1288        }
1289        if !to_delete.is_empty() {
1290            // run before_delete hooks
1291            for am in to_delete_am.clone() {
1292                am.before_delete(db)?;
1293            }
1294            if db.support_returning() {
1295                let deleted = J::delete_many()
1296                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
1297                    .exec_with_returning(db)?;
1298                // run after_delete hooks with the returned value if possible
1299                for am in deleted {
1300                    let am = am.into_active_model();
1301                    let _ = am.after_delete(db)?;
1302                }
1303            } else {
1304                J::delete_many()
1305                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
1306                    .exec(db)?;
1307                // fall back to the saved values if returning is not supported
1308                for am in to_delete_am {
1309                    let _ = am.after_delete(db)?;
1310                }
1311            }
1312        }
1313    }
1314
1315    if !via_models.is_empty() {
1316        // run the before_save hooks
1317        let mut via_models_res = Vec::with_capacity(via_models.len());
1318        for am in via_models {
1319            let am = am.before_save(db, true)?;
1320            via_models_res.push(am);
1321        }
1322
1323        // insert new junctions
1324        if db.support_returning() {
1325            // use the returned value if it is supported
1326            let res = J::insert_many(via_models_res)
1327                .on_conflict_do_nothing()
1328                .exec_with_returning_many(db)?;
1329            // run after_save hooks
1330            if let TryInsertResult::Inserted(inserted) = res {
1331                for model in inserted {
1332                    let _ = J::ActiveModel::after_save(model, db, true)?;
1333                }
1334            }
1335        } else {
1336            // fall back to individual inserts if returning is not supported
1337            for model in via_models_res {
1338                let res = J::insert(model)
1339                    .on_conflict_do_nothing()
1340                    .exec_with_returning(db)?;
1341                if let TryInsertResult::Inserted(model) = res {
1342                    let _ = J::ActiveModel::after_save(model, db, true)?;
1343                }
1344            }
1345        }
1346    }
1347
1348    Ok(())
1349}
1350
1351#[cfg(test)]
1352mod tests {
1353    use crate::{DbErr, entity::*, tests_cfg::*};
1354    use pretty_assertions::assert_eq;
1355
1356    #[cfg(feature = "with-json")]
1357    use serde_json::json;
1358
1359    #[test]
1360    #[cfg(feature = "macros")]
1361    fn test_derive_into_active_model_1() {
1362        mod my_fruit {
1363            pub use super::fruit::*;
1364            use crate as sea_orm;
1365            use crate::entity::prelude::*;
1366
1367            #[derive(DeriveIntoActiveModel)]
1368            pub struct NewFruit {
1369                // id is omitted
1370                pub name: String,
1371                // it is required as opposed to optional in Model
1372                pub cake_id: i32,
1373            }
1374        }
1375
1376        assert_eq!(
1377            my_fruit::NewFruit {
1378                name: "Apple".to_owned(),
1379                cake_id: 1,
1380            }
1381            .into_active_model(),
1382            fruit::ActiveModel {
1383                id: NotSet,
1384                name: Set("Apple".to_owned()),
1385                cake_id: Set(Some(1)),
1386            }
1387        );
1388    }
1389
1390    #[test]
1391    #[cfg(feature = "macros")]
1392    fn test_derive_into_active_model_2() {
1393        use crate as sea_orm;
1394        use crate::entity::prelude::*;
1395
1396        #[derive(DeriveIntoActiveModel)]
1397        #[sea_orm(active_model = "fruit::ActiveModel")]
1398        struct RequiredFruitName {
1399            name: String,
1400        }
1401
1402        assert_eq!(
1403            RequiredFruitName {
1404                name: "Apple Pie".to_owned(),
1405            }
1406            .into_active_model(),
1407            fruit::ActiveModel {
1408                id: NotSet,
1409                name: Set("Apple Pie".to_owned()),
1410                cake_id: NotSet,
1411            }
1412        );
1413
1414        #[derive(DeriveIntoActiveModel)]
1415        #[sea_orm(active_model = "fruit::ActiveModel")]
1416        struct OptionalFruitName {
1417            name: Option<String>,
1418        }
1419
1420        assert_eq!(
1421            OptionalFruitName {
1422                name: Some("Apple Pie".to_owned()),
1423            }
1424            .into_active_model(),
1425            fruit::ActiveModel {
1426                id: NotSet,
1427                name: Set("Apple Pie".to_owned()),
1428                cake_id: NotSet,
1429            }
1430        );
1431
1432        assert_eq!(
1433            OptionalFruitName { name: None }.into_active_model(),
1434            fruit::ActiveModel {
1435                id: NotSet,
1436                name: NotSet,
1437                cake_id: NotSet,
1438            }
1439        );
1440
1441        #[derive(DeriveIntoActiveModel)]
1442        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1443        struct RequiredAndNotNullFruitCake {
1444            cake_id: i32,
1445        }
1446
1447        assert_eq!(
1448            RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1449            fruit::ActiveModel {
1450                id: NotSet,
1451                name: NotSet,
1452                cake_id: Set(Some(1)),
1453            }
1454        );
1455
1456        #[derive(DeriveIntoActiveModel)]
1457        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1458        struct OptionalAndNotNullFruitCake {
1459            cake_id: Option<i32>,
1460        }
1461
1462        assert_eq!(
1463            OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1464            fruit::ActiveModel {
1465                id: NotSet,
1466                name: NotSet,
1467                cake_id: Set(Some(1)),
1468            }
1469        );
1470
1471        assert_eq!(
1472            OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1473            fruit::ActiveModel {
1474                id: NotSet,
1475                name: NotSet,
1476                cake_id: NotSet,
1477            }
1478        );
1479
1480        #[derive(DeriveIntoActiveModel)]
1481        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1482        struct OptionalAndNullableFruitCake {
1483            cake_id: Option<Option<i32>>,
1484        }
1485
1486        assert_eq!(
1487            OptionalAndNullableFruitCake {
1488                cake_id: Some(Some(1)),
1489            }
1490            .into_active_model(),
1491            fruit::ActiveModel {
1492                id: NotSet,
1493                name: NotSet,
1494                cake_id: Set(Some(1)),
1495            }
1496        );
1497
1498        assert_eq!(
1499            OptionalAndNullableFruitCake {
1500                cake_id: Some(None),
1501            }
1502            .into_active_model(),
1503            fruit::ActiveModel {
1504                id: NotSet,
1505                name: NotSet,
1506                cake_id: Set(None),
1507            }
1508        );
1509
1510        assert_eq!(
1511            OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1512            fruit::ActiveModel {
1513                id: NotSet,
1514                name: NotSet,
1515                cake_id: NotSet,
1516            }
1517        );
1518    }
1519
1520    #[test]
1521    #[cfg(feature = "macros")]
1522    fn test_derive_into_active_model_set_single() {
1523        use crate as sea_orm;
1524        use crate::entity::prelude::*;
1525
1526        #[derive(DeriveIntoActiveModel)]
1527        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1528        struct NewFruit {
1529            name: String,
1530        }
1531
1532        assert_eq!(
1533            NewFruit {
1534                name: "Apple".to_owned(),
1535            }
1536            .into_active_model(),
1537            fruit::ActiveModel {
1538                id: NotSet,
1539                name: Set("Apple".to_owned()),
1540                cake_id: Set(None),
1541            }
1542        );
1543    }
1544
1545    #[test]
1546    #[cfg(feature = "macros")]
1547    fn test_derive_into_active_model_set_multiple() {
1548        use crate as sea_orm;
1549        use crate::entity::prelude::*;
1550
1551        #[derive(DeriveIntoActiveModel)]
1552        #[sea_orm(
1553            active_model = "fruit::ActiveModel",
1554            set(name = "String::from(\"cherry\")", cake_id = "None")
1555        )]
1556        struct IdOnlyFruit {
1557            id: i32,
1558        }
1559        assert_eq!(
1560            IdOnlyFruit { id: 1 }.into_active_model(),
1561            fruit::ActiveModel {
1562                id: Set(1),
1563                name: Set("cherry".to_owned()),
1564                cake_id: Set(None),
1565            }
1566        );
1567
1568        #[derive(DeriveIntoActiveModel)]
1569        #[sea_orm(
1570            active_model = "fruit::ActiveModel",
1571            set(name = "String::from(\"cherry\")"),
1572            set(cake_id = "None")
1573        )]
1574        struct IdOnlyFruit2 {
1575            id: i32,
1576        }
1577        assert_eq!(
1578            IdOnlyFruit2 { id: 1 }.into_active_model(),
1579            fruit::ActiveModel {
1580                id: Set(1),
1581                name: Set("cherry".to_owned()),
1582                cake_id: Set(None),
1583            }
1584        );
1585    }
1586
1587    #[test]
1588    #[cfg(feature = "macros")]
1589    fn test_derive_into_active_model_set_separate_attrs() {
1590        use crate as sea_orm;
1591        use crate::entity::prelude::*;
1592
1593        #[derive(DeriveIntoActiveModel)]
1594        #[sea_orm(
1595            active_model = "fruit::ActiveModel",
1596            set(name = "String::from(\"cherry\")")
1597        )]
1598        #[sea_orm(set(cake_id = "None"))]
1599        struct IdOnlyFruit {
1600            id: i32,
1601        }
1602
1603        assert_eq!(
1604            IdOnlyFruit { id: 1 }.into_active_model(),
1605            fruit::ActiveModel {
1606                id: Set(1),
1607                name: Set("cherry".to_owned()),
1608                cake_id: Set(None),
1609            }
1610        );
1611    }
1612
1613    #[test]
1614    #[cfg(feature = "macros")]
1615    fn test_derive_into_active_model_ignore() {
1616        use crate as sea_orm;
1617        use crate::entity::prelude::*;
1618
1619        #[derive(DeriveIntoActiveModel)]
1620        #[sea_orm(active_model = "fruit::ActiveModel")]
1621        struct NewFruit {
1622            name: String,
1623            cake_id: i32,
1624            #[sea_orm(ignore)]
1625            _extra: String,
1626        }
1627
1628        assert_eq!(
1629            NewFruit {
1630                name: "Apple".to_owned(),
1631                cake_id: 1,
1632                _extra: "ignored".to_owned(),
1633            }
1634            .into_active_model(),
1635            fruit::ActiveModel {
1636                id: NotSet,
1637                name: Set("Apple".to_owned()),
1638                cake_id: Set(Some(1)),
1639            }
1640        );
1641    }
1642
1643    #[test]
1644    #[cfg(feature = "macros")]
1645    fn test_derive_into_active_model_skip() {
1646        use crate as sea_orm;
1647        use crate::entity::prelude::*;
1648
1649        #[derive(DeriveIntoActiveModel)]
1650        #[sea_orm(active_model = "fruit::ActiveModel")]
1651        struct NewFruit {
1652            name: String,
1653            #[sea_orm(skip)]
1654            _extra: String,
1655        }
1656
1657        assert_eq!(
1658            NewFruit {
1659                name: "Apple".to_owned(),
1660                _extra: "skipped".to_owned(),
1661            }
1662            .into_active_model(),
1663            fruit::ActiveModel {
1664                id: NotSet,
1665                name: Set("Apple".to_owned()),
1666                cake_id: NotSet,
1667            }
1668        );
1669    }
1670
1671    #[test]
1672    #[cfg(feature = "macros")]
1673    fn test_derive_into_active_model_set_and_ignore() {
1674        use crate as sea_orm;
1675        use crate::entity::prelude::*;
1676
1677        #[derive(DeriveIntoActiveModel)]
1678        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
1679        struct NewFruit {
1680            name: String,
1681            #[sea_orm(ignore)]
1682            _extra: String,
1683        }
1684
1685        assert_eq!(
1686            NewFruit {
1687                name: "Apple".to_owned(),
1688                _extra: "ignored".to_owned(),
1689            }
1690            .into_active_model(),
1691            fruit::ActiveModel {
1692                id: NotSet,
1693                name: Set("Apple".to_owned()),
1694                cake_id: Set(Some(42)),
1695            }
1696        );
1697    }
1698
1699    #[test]
1700    #[cfg(feature = "macros")]
1701    fn test_derive_into_active_model_foreign_ignore() {
1702        use serde::{Deserialize, Serialize};
1703
1704        use crate as sea_orm;
1705        use crate::entity::prelude::*;
1706
1707        #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
1708        #[sea_orm(active_model = "fruit::ActiveModel")]
1709        struct NewFruit {
1710            #[sea_orm(ignore)]
1711            id: i32,
1712            name: String,
1713            #[serde(skip)]
1714            cake_id: Option<i32>,
1715        }
1716
1717        assert_eq!(
1718            NewFruit {
1719                id: 1.to_owned(),
1720                name: "Apple".to_owned(),
1721                cake_id: Some(42)
1722            }
1723            .into_active_model(),
1724            fruit::ActiveModel {
1725                id: NotSet,
1726                name: Set("Apple".to_owned()),
1727                cake_id: Set(Some(42)),
1728            }
1729        );
1730    }
1731
1732    #[test]
1733    #[cfg(feature = "macros")]
1734    fn test_derive_into_active_model_exhaustive() {
1735        use crate as sea_orm;
1736        use crate::entity::prelude::*;
1737
1738        #[derive(DeriveIntoActiveModel)]
1739        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1740        struct FullFruit {
1741            id: i32,
1742            name: String,
1743        }
1744
1745        assert_eq!(
1746            FullFruit {
1747                id: 1,
1748                name: "Apple".to_owned(),
1749            }
1750            .into_active_model(),
1751            fruit::ActiveModel {
1752                id: Set(1),
1753                name: Set("Apple".to_owned()),
1754                cake_id: Set(None),
1755            }
1756        );
1757    }
1758
1759    #[test]
1760    #[cfg(feature = "macros")]
1761    fn test_derive_into_active_model_multiple_sets() {
1762        use crate as sea_orm;
1763        use crate::entity::prelude::*;
1764
1765        const DEFULT_CAKE_ID: i32 = 1;
1766        #[derive(DeriveIntoActiveModel)]
1767        #[sea_orm(
1768            active_model = "fruit::ActiveModel",
1769            exhaustive,
1770            set(cake_id = "Some(DEFULT_CAKE_ID)")
1771        )]
1772        struct FullFruit {
1773            id: i32,
1774            name: String,
1775        }
1776
1777        assert_eq!(
1778            FullFruit {
1779                id: 1,
1780                name: "Apple".to_owned(),
1781            }
1782            .into_active_model(),
1783            fruit::ActiveModel {
1784                id: Set(1),
1785                name: Set("Apple".to_owned()),
1786                cake_id: Set(Some(1)),
1787            }
1788        );
1789    }
1790
1791    #[test]
1792    #[cfg(feature = "macros")]
1793    fn test_derive_into_active_model_field_empty_default() {
1794        use crate as sea_orm;
1795        use crate::entity::prelude::*;
1796
1797        #[derive(DeriveIntoActiveModel)]
1798        #[sea_orm(active_model = "fruit::ActiveModel")]
1799        struct NewFruit {
1800            #[sea_orm(default)]
1801            name: Option<String>,
1802        }
1803
1804        // Some(v) -> Set(v)
1805        assert_eq!(
1806            NewFruit {
1807                name: Some("Apple".to_owned()),
1808            }
1809            .into_active_model(),
1810            fruit::ActiveModel {
1811                id: NotSet,
1812                name: Set("Apple".to_owned()),
1813                cake_id: NotSet,
1814            }
1815        );
1816
1817        // None -> Set(fallback)
1818        assert_eq!(
1819            NewFruit { name: None }.into_active_model(),
1820            fruit::ActiveModel {
1821                id: NotSet,
1822                name: Set("".to_owned()),
1823                cake_id: NotSet,
1824            }
1825        );
1826    }
1827
1828    #[test]
1829    #[cfg(feature = "macros")]
1830    fn test_derive_into_active_model_field_custom_option() {
1831        use crate as sea_orm;
1832        use crate::entity::prelude::*;
1833        mod foreign_crate {
1834            #[derive(Debug, Clone, PartialEq, Eq)]
1835            pub enum CustomOption<T> {
1836                None,
1837                Some(T),
1838            }
1839
1840            impl From<CustomOption<String>> for Option<String> {
1841                fn from(option: CustomOption<String>) -> Self {
1842                    match option {
1843                        CustomOption::None => Option::None,
1844                        CustomOption::Some(value) => value.into(),
1845                    }
1846                }
1847            }
1848        }
1849        use foreign_crate::CustomOption;
1850
1851        #[derive(DeriveIntoActiveModel)]
1852        #[sea_orm(active_model = "fruit::ActiveModel")]
1853        struct NewFruit {
1854            #[sea_orm(default)]
1855            name: CustomOption<String>,
1856        }
1857
1858        // Some(v) -> Set(v)
1859        assert_eq!(
1860            NewFruit {
1861                name: CustomOption::Some("Apple".to_owned()),
1862            }
1863            .into_active_model(),
1864            fruit::ActiveModel {
1865                id: NotSet,
1866                name: Set("Apple".to_owned()),
1867                cake_id: NotSet,
1868            }
1869        );
1870
1871        // None -> Set(fallback)
1872        assert_eq!(
1873            NewFruit {
1874                name: CustomOption::None
1875            }
1876            .into_active_model(),
1877            fruit::ActiveModel {
1878                id: NotSet,
1879                name: Set("".to_owned()),
1880                cake_id: NotSet,
1881            }
1882        );
1883    }
1884
1885    #[test]
1886    #[cfg(feature = "macros")]
1887    fn test_derive_into_active_model_field_default_some() {
1888        use crate as sea_orm;
1889        use crate::entity::prelude::*;
1890
1891        #[derive(DeriveIntoActiveModel)]
1892        #[sea_orm(active_model = "fruit::ActiveModel")]
1893        struct NewFruit {
1894            #[sea_orm(default = "String::from(\"Unnamed\")")]
1895            name: Option<String>,
1896        }
1897
1898        // Some(v) -> Set(v)
1899        assert_eq!(
1900            NewFruit {
1901                name: Some("Apple".to_owned()),
1902            }
1903            .into_active_model(),
1904            fruit::ActiveModel {
1905                id: NotSet,
1906                name: Set("Apple".to_owned()),
1907                cake_id: NotSet,
1908            }
1909        );
1910
1911        // None -> Set(fallback)
1912        assert_eq!(
1913            NewFruit { name: None }.into_active_model(),
1914            fruit::ActiveModel {
1915                id: NotSet,
1916                name: Set("Unnamed".to_owned()),
1917                cake_id: NotSet,
1918            }
1919        );
1920    }
1921
1922    #[test]
1923    #[cfg(feature = "macros")]
1924    fn test_derive_into_active_model_field_default_with_set() {
1925        use crate as sea_orm;
1926        use crate::entity::prelude::*;
1927
1928        #[derive(DeriveIntoActiveModel)]
1929        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
1930        struct NewFruit {
1931            #[sea_orm(default = "String::from(\"Unnamed\")")]
1932            name: Option<String>,
1933            #[sea_orm(ignore)]
1934            _extra: String,
1935        }
1936
1937        assert_eq!(
1938            NewFruit {
1939                name: Some("Apple".to_owned()),
1940                _extra: "ignored".to_owned(),
1941            }
1942            .into_active_model(),
1943            fruit::ActiveModel {
1944                id: NotSet,
1945                name: Set("Apple".to_owned()),
1946                cake_id: Set(Some(99)),
1947            }
1948        );
1949
1950        assert_eq!(
1951            NewFruit {
1952                name: None,
1953                _extra: "ignored".to_owned(),
1954            }
1955            .into_active_model(),
1956            fruit::ActiveModel {
1957                id: NotSet,
1958                name: Set("Unnamed".to_owned()),
1959                cake_id: Set(Some(99)),
1960            }
1961        );
1962    }
1963
1964    #[test]
1965    #[cfg(feature = "macros")]
1966    fn test_derive_into_active_model_field_default_exhaustive() {
1967        use crate as sea_orm;
1968        use crate::entity::prelude::*;
1969
1970        #[derive(DeriveIntoActiveModel)]
1971        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1972        struct NewFruit {
1973            id: i32,
1974            #[sea_orm(default = "String::from(\"Unnamed\")")]
1975            name: Option<String>,
1976        }
1977
1978        assert_eq!(
1979            NewFruit {
1980                id: 1,
1981                name: Some("Apple".to_owned()),
1982            }
1983            .into_active_model(),
1984            fruit::ActiveModel {
1985                id: Set(1),
1986                name: Set("Apple".to_owned()),
1987                cake_id: Set(None),
1988            }
1989        );
1990
1991        assert_eq!(
1992            NewFruit { id: 2, name: None }.into_active_model(),
1993            fruit::ActiveModel {
1994                id: Set(2),
1995                name: Set("Unnamed".to_owned()),
1996                cake_id: Set(None),
1997            }
1998        );
1999    }
2000
2001    #[test]
2002    #[cfg(feature = "macros")]
2003    fn test_derive_try_into_model_1() {
2004        mod my_fruit {
2005            use crate as sea_orm;
2006            use crate::entity::prelude::*;
2007
2008            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2009            #[sea_orm(table_name = "fruit")]
2010            pub struct Model {
2011                #[sea_orm(primary_key)]
2012                pub id: i32,
2013                pub name: String,
2014                pub cake_id: Option<i32>,
2015            }
2016
2017            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2018            pub enum Relation {}
2019
2020            impl ActiveModelBehavior for ActiveModel {}
2021        }
2022        assert_eq!(
2023            my_fruit::ActiveModel {
2024                id: Set(1),
2025                name: Set("Pineapple".to_owned()),
2026                cake_id: Set(None),
2027            }
2028            .try_into_model()
2029            .unwrap(),
2030            my_fruit::Model {
2031                id: 1,
2032                name: "Pineapple".to_owned(),
2033                cake_id: None,
2034            }
2035        );
2036
2037        assert_eq!(
2038            my_fruit::ActiveModel {
2039                id: Set(2),
2040                name: Set("Apple".to_owned()),
2041                cake_id: Set(Some(1)),
2042            }
2043            .try_into_model()
2044            .unwrap(),
2045            my_fruit::Model {
2046                id: 2,
2047                name: "Apple".to_owned(),
2048                cake_id: Some(1),
2049            }
2050        );
2051
2052        assert_eq!(
2053            my_fruit::ActiveModel {
2054                id: Set(1),
2055                name: NotSet,
2056                cake_id: Set(None),
2057            }
2058            .try_into_model(),
2059            Err(DbErr::AttrNotSet(String::from("name")))
2060        );
2061
2062        assert_eq!(
2063            my_fruit::ActiveModel {
2064                id: Set(1),
2065                name: Set("Pineapple".to_owned()),
2066                cake_id: NotSet,
2067            }
2068            .try_into_model(),
2069            Err(DbErr::AttrNotSet(String::from("cake_id")))
2070        );
2071    }
2072
2073    #[test]
2074    #[cfg(feature = "macros")]
2075    fn test_derive_try_into_model_2() {
2076        mod my_fruit {
2077            use crate as sea_orm;
2078            use crate::entity::prelude::*;
2079
2080            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2081            #[sea_orm(table_name = "fruit")]
2082            pub struct Model {
2083                #[sea_orm(primary_key)]
2084                pub id: i32,
2085                pub name: String,
2086                #[sea_orm(ignore)]
2087                pub cake_id: Option<i32>,
2088            }
2089
2090            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2091            pub enum Relation {}
2092
2093            impl ActiveModelBehavior for ActiveModel {}
2094        }
2095        assert_eq!(
2096            my_fruit::ActiveModel {
2097                id: Set(1),
2098                name: Set("Pineapple".to_owned()),
2099            }
2100            .try_into_model()
2101            .unwrap(),
2102            my_fruit::Model {
2103                id: 1,
2104                name: "Pineapple".to_owned(),
2105                cake_id: None,
2106            }
2107        );
2108    }
2109
2110    #[test]
2111    #[cfg(feature = "macros")]
2112    fn test_derive_try_into_model_3() {
2113        mod my_fruit {
2114            use crate as sea_orm;
2115            use crate::entity::prelude::*;
2116
2117            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2118            #[sea_orm(table_name = "fruit")]
2119            pub struct Model {
2120                #[sea_orm(primary_key)]
2121                pub id: i32,
2122                #[sea_orm(ignore)]
2123                pub name: String,
2124                pub cake_id: Option<i32>,
2125            }
2126
2127            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2128            pub enum Relation {}
2129
2130            impl ActiveModelBehavior for ActiveModel {}
2131        }
2132        assert_eq!(
2133            my_fruit::ActiveModel {
2134                id: Set(1),
2135                cake_id: Set(Some(1)),
2136            }
2137            .try_into_model()
2138            .unwrap(),
2139            my_fruit::Model {
2140                id: 1,
2141                name: "".to_owned(),
2142                cake_id: Some(1),
2143            }
2144        );
2145    }
2146
2147    #[test]
2148    #[cfg(feature = "with-json")]
2149    fn test_active_model_set_from_json_1() {
2150        assert_eq!(
2151            cake::ActiveModel::from_json(json!({
2152                "id": 1,
2153                "name": "Apple Pie",
2154            }))
2155            .unwrap(),
2156            cake::ActiveModel {
2157                id: Set(1),
2158                name: Set("Apple Pie".to_owned()),
2159            }
2160        );
2161
2162        assert_eq!(
2163            cake::ActiveModel::from_json(json!({
2164                "id": 1,
2165            }))
2166            .unwrap(),
2167            cake::ActiveModel {
2168                id: Set(1),
2169                name: NotSet,
2170            }
2171        );
2172
2173        assert_eq!(
2174            cake::ActiveModel::from_json(json!({
2175                "name": "Apple Pie",
2176            }))
2177            .unwrap(),
2178            cake::ActiveModel {
2179                id: NotSet,
2180                name: Set("Apple Pie".to_owned()),
2181            }
2182        );
2183
2184        let mut cake: cake::ActiveModel = Default::default();
2185        cake.set_from_json(json!({
2186            "name": "Apple Pie",
2187        }))
2188        .unwrap();
2189        assert_eq!(
2190            cake,
2191            cake::ActiveModel {
2192                id: NotSet,
2193                name: Set("Apple Pie".to_owned()),
2194            }
2195        );
2196    }
2197
2198    #[test]
2199    #[cfg(feature = "with-json")]
2200    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
2201        let mut fruit: fruit::ActiveModel = Default::default();
2202
2203        fruit.set_from_json(json!({
2204            "name": "Apple",
2205        }))?;
2206        assert_eq!(
2207            fruit,
2208            fruit::ActiveModel {
2209                id: ActiveValue::NotSet,
2210                name: ActiveValue::Set("Apple".to_owned()),
2211                cake_id: ActiveValue::NotSet,
2212            }
2213        );
2214
2215        assert_eq!(
2216            fruit::ActiveModel::from_json(json!({
2217                "name": "Apple",
2218            }))?,
2219            fruit::ActiveModel {
2220                id: ActiveValue::NotSet,
2221                name: ActiveValue::Set("Apple".to_owned()),
2222                cake_id: ActiveValue::NotSet,
2223            }
2224        );
2225
2226        fruit.set_from_json(json!({
2227            "name": "Apple",
2228            "cake_id": null,
2229        }))?;
2230        assert_eq!(
2231            fruit,
2232            fruit::ActiveModel {
2233                id: ActiveValue::NotSet,
2234                name: ActiveValue::Set("Apple".to_owned()),
2235                cake_id: ActiveValue::Set(None),
2236            }
2237        );
2238
2239        fruit.set_from_json(json!({
2240            "id": null,
2241            "name": "Apple",
2242            "cake_id": 1,
2243        }))?;
2244        assert_eq!(
2245            fruit,
2246            fruit::ActiveModel {
2247                id: ActiveValue::NotSet,
2248                name: ActiveValue::Set("Apple".to_owned()),
2249                cake_id: ActiveValue::Set(Some(1)),
2250            }
2251        );
2252
2253        fruit.set_from_json(json!({
2254            "id": 2,
2255            "name": "Apple",
2256            "cake_id": 1,
2257        }))?;
2258        assert_eq!(
2259            fruit,
2260            fruit::ActiveModel {
2261                id: ActiveValue::NotSet,
2262                name: ActiveValue::Set("Apple".to_owned()),
2263                cake_id: ActiveValue::Set(Some(1)),
2264            }
2265        );
2266
2267        let mut fruit = fruit::ActiveModel {
2268            id: ActiveValue::Set(1),
2269            name: ActiveValue::NotSet,
2270            cake_id: ActiveValue::NotSet,
2271        };
2272        fruit.set_from_json(json!({
2273            "id": 8,
2274            "name": "Apple",
2275            "cake_id": 1,
2276        }))?;
2277        assert_eq!(
2278            fruit,
2279            fruit::ActiveModel {
2280                id: ActiveValue::Set(1),
2281                name: ActiveValue::Set("Apple".to_owned()),
2282                cake_id: ActiveValue::Set(Some(1)),
2283            }
2284        );
2285
2286        Ok(())
2287    }
2288
2289    #[test]
2290    #[cfg(feature = "with-json")]
2291    fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
2292        use crate::*;
2293
2294        let db = MockDatabase::new(DbBackend::Postgres)
2295            .append_exec_results([
2296                MockExecResult {
2297                    last_insert_id: 1,
2298                    rows_affected: 1,
2299                },
2300                MockExecResult {
2301                    last_insert_id: 1,
2302                    rows_affected: 1,
2303                },
2304            ])
2305            .append_query_results([
2306                [fruit::Model {
2307                    id: 1,
2308                    name: "Apple".to_owned(),
2309                    cake_id: None,
2310                }],
2311                [fruit::Model {
2312                    id: 2,
2313                    name: "Orange".to_owned(),
2314                    cake_id: Some(1),
2315                }],
2316            ])
2317            .into_connection();
2318
2319        let mut fruit: fruit::ActiveModel = Default::default();
2320        fruit.set_from_json(json!({
2321            "name": "Apple",
2322        }))?;
2323        fruit.save(&db)?;
2324
2325        let mut fruit = fruit::ActiveModel {
2326            id: Set(2),
2327            ..Default::default()
2328        };
2329        fruit.set_from_json(json!({
2330            "id": 9,
2331            "name": "Orange",
2332            "cake_id": 1,
2333        }))?;
2334        fruit.save(&db)?;
2335
2336        assert_eq!(
2337            db.into_transaction_log(),
2338            [
2339                Transaction::from_sql_and_values(
2340                    DbBackend::Postgres,
2341                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
2342                    ["Apple".into()],
2343                ),
2344                Transaction::from_sql_and_values(
2345                    DbBackend::Postgres,
2346                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2347                    ["Orange".into(), 1i32.into(), 2i32.into()],
2348                ),
2349            ]
2350        );
2351
2352        Ok(())
2353    }
2354
2355    #[test]
2356    fn test_active_model_is_changed() {
2357        let mut fruit: fruit::ActiveModel = Default::default();
2358        assert!(!fruit.is_changed());
2359
2360        fruit.set(fruit::Column::Name, "apple".into());
2361        assert!(fruit.is_changed());
2362
2363        let mut fruit = fruit::Model {
2364            id: 1,
2365            name: "".into(),
2366            cake_id: None,
2367        };
2368        fruit.set("name".parse().unwrap(), "orange".into());
2369        assert_eq!(fruit.name, "orange");
2370    }
2371
2372    #[test]
2373    fn test_reset_1() {
2374        assert_eq!(
2375            fruit::Model {
2376                id: 1,
2377                name: "Apple".into(),
2378                cake_id: None,
2379            }
2380            .into_active_model(),
2381            fruit::ActiveModel {
2382                id: Unchanged(1),
2383                name: Unchanged("Apple".into()),
2384                cake_id: Unchanged(None)
2385            },
2386        );
2387
2388        assert_eq!(
2389            fruit::Model {
2390                id: 1,
2391                name: "Apple".into(),
2392                cake_id: None,
2393            }
2394            .into_active_model()
2395            .reset_all(),
2396            fruit::ActiveModel {
2397                id: Set(1),
2398                name: Set("Apple".into()),
2399                cake_id: Set(None)
2400            },
2401        );
2402
2403        assert_eq!(
2404            fruit::Model {
2405                id: 1,
2406                name: "Apple".into(),
2407                cake_id: Some(2),
2408            }
2409            .into_active_model(),
2410            fruit::ActiveModel {
2411                id: Unchanged(1),
2412                name: Unchanged("Apple".into()),
2413                cake_id: Unchanged(Some(2)),
2414            },
2415        );
2416
2417        assert_eq!(
2418            fruit::Model {
2419                id: 1,
2420                name: "Apple".into(),
2421                cake_id: Some(2),
2422            }
2423            .into_active_model()
2424            .reset_all(),
2425            fruit::ActiveModel {
2426                id: Set(1),
2427                name: Set("Apple".into()),
2428                cake_id: Set(Some(2)),
2429            },
2430        );
2431    }
2432
2433    #[test]
2434    fn test_reset_2() -> Result<(), DbErr> {
2435        use crate::*;
2436
2437        let db = MockDatabase::new(DbBackend::Postgres)
2438            .append_exec_results(vec![
2439                MockExecResult {
2440                    last_insert_id: 1,
2441                    rows_affected: 1,
2442                },
2443                MockExecResult {
2444                    last_insert_id: 1,
2445                    rows_affected: 1,
2446                },
2447            ])
2448            .append_query_results(vec![
2449                vec![fruit::Model {
2450                    id: 1,
2451                    name: "Apple".to_owned(),
2452                    cake_id: None,
2453                }],
2454                vec![fruit::Model {
2455                    id: 1,
2456                    name: "Apple".to_owned(),
2457                    cake_id: None,
2458                }],
2459            ])
2460            .into_connection();
2461
2462        fruit::Model {
2463            id: 1,
2464            name: "Apple".into(),
2465            cake_id: None,
2466        }
2467        .into_active_model()
2468        .update(&db)?;
2469
2470        fruit::Model {
2471            id: 1,
2472            name: "Apple".into(),
2473            cake_id: None,
2474        }
2475        .into_active_model()
2476        .reset_all()
2477        .update(&db)?;
2478
2479        assert_eq!(
2480            db.into_transaction_log(),
2481            vec![
2482                Transaction::from_sql_and_values(
2483                    DbBackend::Postgres,
2484                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
2485                    vec![1i32.into(), 1u64.into()],
2486                ),
2487                Transaction::from_sql_and_values(
2488                    DbBackend::Postgres,
2489                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2490                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
2491                ),
2492            ]
2493        );
2494
2495        Ok(())
2496    }
2497
2498    #[test]
2499    fn test_active_model_default_values() {
2500        assert_eq!(
2501            fruit::ActiveModel::default_values(),
2502            fruit::ActiveModel {
2503                id: Set(0),
2504                name: Set("".into()),
2505                cake_id: Set(None),
2506            },
2507        );
2508
2509        assert_eq!(
2510            lunch_set::ActiveModel::default_values(),
2511            lunch_set::ActiveModel {
2512                id: Set(0),
2513                name: Set("".into()),
2514                tea: NotSet,
2515            },
2516        );
2517    }
2518
2519    #[test]
2520    fn test_active_model_set_parent_key() {
2521        let mut fruit = fruit::Model {
2522            id: 2,
2523            name: "F".into(),
2524            cake_id: None,
2525        }
2526        .into_active_model();
2527
2528        let cake = cake::Model {
2529            id: 4,
2530            name: "C".into(),
2531        }
2532        .into_active_model();
2533
2534        fruit.set_parent_key(&cake).unwrap();
2535
2536        assert_eq!(
2537            fruit,
2538            fruit::ActiveModel {
2539                id: Unchanged(2),
2540                name: Unchanged("F".into()),
2541                cake_id: Set(Some(4)),
2542            }
2543        );
2544
2545        assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
2546
2547        assert_eq!(
2548            fruit,
2549            fruit::ActiveModel {
2550                id: Unchanged(2),
2551                name: Unchanged("F".into()),
2552                cake_id: Set(None),
2553            }
2554        );
2555
2556        let mut cake_filling = cake_filling::ActiveModel::new();
2557
2558        cake_filling.set_parent_key(&cake).unwrap();
2559
2560        assert_eq!(
2561            cake_filling,
2562            cake_filling::ActiveModel {
2563                cake_id: Set(4),
2564                filling_id: NotSet,
2565            }
2566        );
2567    }
2568}