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    /// Like find_related, but infer type from `AM`
893    #[doc(hidden)]
894    fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
895    where
896        AM: ActiveModelTrait,
897        Self::Entity: Related<AM::Entity>,
898    {
899        self.find_related(AM::Entity::default())
900    }
901
902    /// Establish links between self and a related Entity for a many-to-many relation.
903    /// New associations will be added, and leftovers can be optionally deleted.
904    #[doc(hidden)]
905    fn establish_links<J, R, RM, C>(
906        &self,
907        _: J,
908        related_models: &[RM],
909        delete_leftover: bool,
910        db: &C,
911    ) -> Result<(), DbErr>
912    where
913        R: EntityTrait,
914        RM: ActiveModelTrait<Entity = R>,
915        J: EntityTrait + Related<R> + Related<Self::Entity>,
916        J::Model: IntoActiveModel<J::ActiveModel>,
917        J::ActiveModel: ActiveModelBehavior,
918        C: ConnectionTrait,
919    {
920        let left = <J as Related<Self::Entity>>::to();
921        let right = <J as Related<R>>::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
927    #[doc(hidden)]
928    fn establish_links_self<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>>::via().rev();
944        let right = <Self::Entity as RelatedSelfVia<J>>::to();
945
946        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
947    }
948
949    /// Establish links for self-referencing many-to-many relation, but left-right reversed
950    #[doc(hidden)]
951    fn establish_links_self_rev<J, RM, C>(
952        &self,
953        _: J,
954        related_models: &[RM],
955        delete_leftover: bool,
956        db: &C,
957    ) -> Result<(), DbErr>
958    where
959        RM: ActiveModelTrait<Entity = Self::Entity>,
960        J: EntityTrait,
961        J::Model: IntoActiveModel<J::ActiveModel>,
962        J::ActiveModel: ActiveModelBehavior,
963        C: ConnectionTrait,
964        Self::Entity: RelatedSelfVia<J>,
965    {
966        let left = <Self::Entity as RelatedSelfVia<J>>::to();
967        let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();
968
969        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
970    }
971
972    /// Inverse of establish link, break links between two many-to-many models
973    #[doc(hidden)]
974    fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
975    where
976        J: EntityTrait + Related<Self::Entity>,
977        C: ConnectionTrait,
978    {
979        let rel_def = <J as Related<Self::Entity>>::to();
980        let id = get_key_from_active_model(&rel_def.to_col, self)?;
981
982        J::delete_many()
983            .filter(
984                column_tuple_in_condition(
985                    &rel_def.from_tbl,
986                    &rel_def.from_col,
987                    &[id],
988                    db.get_database_backend(),
989                )
990                .expect(""),
991            )
992            .exec(db)
993    }
994
995    /// Like `delete_links` but for self-referencing relations
996    #[doc(hidden)]
997    fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
998    where
999        J: EntityTrait,
1000        C: ConnectionTrait,
1001        Self::Entity: RelatedSelfVia<J>,
1002    {
1003        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
1004        let right = <Self::Entity as RelatedSelfVia<J>>::to();
1005
1006        let id = get_key_from_active_model(&left.to_col, self)?;
1007
1008        if left.to_col != right.to_col {
1009            return Err(DbErr::Type("Expect Self Referencing Relation".into()));
1010        }
1011
1012        J::delete_many()
1013            .filter(
1014                Condition::any()
1015                    .add(
1016                        column_tuple_in_condition(
1017                            &left.from_tbl,
1018                            &left.from_col,
1019                            std::slice::from_ref(&id),
1020                            db.get_database_backend(),
1021                        )
1022                        .expect(""),
1023                    )
1024                    .add(
1025                        column_tuple_in_condition(
1026                            &right.from_tbl,
1027                            &right.from_col,
1028                            std::slice::from_ref(&id),
1029                            db.get_database_backend(),
1030                        )
1031                        .expect(""),
1032                    ),
1033            )
1034            .exec(db)
1035    }
1036}
1037
1038/// Lifecycle hooks for an [`ActiveModelTrait`].
1039///
1040/// Every entity must have an impl of this trait — even the empty
1041/// `impl ActiveModelBehavior for ActiveModel {}` you see in the examples is
1042/// required so that the default `new` / `before_save` / `after_save` /
1043/// `before_delete` / `after_delete` implementations are wired up. Override
1044/// the hooks to enforce invariants, populate computed columns, or run side
1045/// effects around saves and deletes.
1046///
1047/// ```ignore
1048/// use sea_orm::entity::prelude::*;
1049///
1050/// impl ActiveModelBehavior for ActiveModel {
1051///     fn before_save<C>(mut self, _db: &C, insert: bool) -> Result<Self, DbErr>
1052///     where
1053///         C: ConnectionTrait,
1054///     {
1055///         if insert && self.created_at.is_not_set() {
1056///             self.created_at = Set(chrono::Utc::now());
1057///         }
1058///         self.updated_at = Set(chrono::Utc::now());
1059///         Ok(self)
1060///     }
1061/// }
1062/// ```
1063#[allow(unused_variables)]
1064pub trait ActiveModelBehavior: ActiveModelTrait {
1065    /// Build a fresh ActiveModel. Defaults to [`ActiveModelTrait::default`]
1066    /// (every column `NotSet`); override to pre-fill columns:
1067    ///
1068    /// ```ignore
1069    /// fn new() -> Self {
1070    ///     Self {
1071    ///         status: Set(Status::New),
1072    ///         ..ActiveModelTrait::default()
1073    ///     }
1074    /// }
1075    /// ```
1076    fn new() -> Self {
1077        <Self as ActiveModelTrait>::default()
1078    }
1079
1080    /// Hook invoked before `insert`, `update`, and `save`. `insert` is `true`
1081    /// for inserts. Return an error to abort the operation.
1082    fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
1083    where
1084        C: ConnectionTrait,
1085    {
1086        Ok(self)
1087    }
1088
1089    /// Hook invoked after `insert`, `update`, and `save` succeed. Receives
1090    /// (and may transform) the resulting `Model`.
1091    fn after_save<C>(
1092        model: <Self::Entity as EntityTrait>::Model,
1093        db: &C,
1094        insert: bool,
1095    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
1096    where
1097        C: ConnectionTrait,
1098    {
1099        Ok(model)
1100    }
1101
1102    /// Hook invoked before `delete`. Return an error to abort.
1103    fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
1104    where
1105        C: ConnectionTrait,
1106    {
1107        Ok(self)
1108    }
1109
1110    /// Hook invoked after `delete` succeeds.
1111    fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
1112    where
1113        C: ConnectionTrait,
1114    {
1115        Ok(self)
1116    }
1117}
1118
1119/// A Trait for any type that can be converted into an `ActiveModel`,
1120/// can be derived using `DeriveIntoActiveModel`.
1121///
1122/// ## Derive Macro Example
1123///
1124/// ```rust
1125/// use sea_orm::DeriveIntoActiveModel;
1126/// mod fruit {
1127///     use sea_orm::entity::prelude::*;
1128///     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1129///     #[sea_orm(table_name = "fruit")]
1130///     pub struct Model {
1131///         #[sea_orm(primary_key)]
1132///         pub id: i32,
1133///         pub name: String,
1134///         pub cake_id: Option<i32>,
1135///     }
1136///     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1137///     pub enum Relation {}
1138///     impl ActiveModelBehavior for ActiveModel {}
1139/// }
1140///
1141/// #[derive(DeriveIntoActiveModel)]
1142/// #[sea_orm(active_model = "fruit::ActiveModel")]
1143/// struct NewFruit {
1144///     name: String,
1145///     // `id` and `cake_id` are omitted - they become `NotSet`
1146/// }
1147/// ```
1148///
1149/// ## `set(...)` - always set absent ActiveModel fields
1150///
1151/// ```rust
1152/// # mod fruit {
1153/// #     use sea_orm::entity::prelude::*;
1154/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1155/// #     #[sea_orm(table_name = "fruit")]
1156/// #     pub struct Model {
1157/// #         #[sea_orm(primary_key)]
1158/// #         pub id: i32,
1159/// #         pub name: String,
1160/// #         pub cake_id: Option<i32>,
1161/// #     }
1162/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1163/// #     pub enum Relation {}
1164/// #     impl ActiveModelBehavior for ActiveModel {}
1165/// # }
1166/// use sea_orm::DeriveIntoActiveModel;
1167///
1168/// #[derive(DeriveIntoActiveModel)]
1169/// #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1170/// struct NewFruit {
1171///     name: String,
1172///     // `cake_id` is not on the struct, but will always be `Set(None)`
1173/// }
1174/// ```
1175///
1176/// ## `default = "expr"` - fallback for `Option<T>` struct fields
1177///
1178/// ```rust
1179/// # mod fruit {
1180/// #     use sea_orm::entity::prelude::*;
1181/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
1182/// #     #[sea_orm(table_name = "fruit")]
1183/// #     pub struct Model {
1184/// #         #[sea_orm(primary_key)]
1185/// #         pub id: i32,
1186/// #         pub name: String,
1187/// #         pub cake_id: Option<i32>,
1188/// #     }
1189/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1190/// #     pub enum Relation {}
1191/// #     impl ActiveModelBehavior for ActiveModel {}
1192/// # }
1193/// use sea_orm::DeriveIntoActiveModel;
1194///
1195/// #[derive(DeriveIntoActiveModel)]
1196/// #[sea_orm(active_model = "fruit::ActiveModel")]
1197/// struct UpdateFruit {
1198///     /// `Some("Apple")` -> `Set("Apple")`, `None` ->`Set("Unnamed")`
1199///     #[sea_orm(default = "String::from(\"Unnamed\")")]
1200///     name: Option<String>,
1201/// }
1202/// ```
1203pub trait IntoActiveModel<A>
1204where
1205    A: ActiveModelTrait,
1206{
1207    /// Method to call to perform the conversion
1208    fn into_active_model(self) -> A;
1209}
1210
1211impl<A> IntoActiveModel<A> for A
1212where
1213    A: ActiveModelTrait,
1214{
1215    fn into_active_model(self) -> A {
1216        self
1217    }
1218}
1219
1220fn establish_links<EM, J, RM, C>(
1221    model: &EM,
1222    related_models: &[RM],
1223    left: RelationDef,
1224    right: RelationDef,
1225    delete_leftover: bool,
1226    db: &C,
1227) -> Result<(), DbErr>
1228where
1229    EM: ActiveModelTrait,
1230    RM: ActiveModelTrait,
1231    J: EntityTrait,
1232    J::Model: IntoActiveModel<J::ActiveModel>,
1233    J::ActiveModel: ActiveModelBehavior,
1234    C: ConnectionTrait,
1235{
1236    let mut require_leftover = true;
1237
1238    if related_models.is_empty() {
1239        // if there are no related models, then there is no risk of insert conflict
1240        require_leftover = false;
1241    }
1242
1243    let primary_key = J::primary_key_identity();
1244    if require_leftover
1245        && primary_key.fully_contains(&left.from_col)
1246        && primary_key.fully_contains(&right.from_col)
1247    {
1248        // if the primary key is a composite key of the two relations
1249        // we can use on conflict no action safely
1250        require_leftover = false;
1251    }
1252
1253    let mut leftover = Vec::new();
1254    if delete_leftover || require_leftover {
1255        for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
1256            &left,
1257            model,
1258            db.get_database_backend(),
1259        )?
1260        .all(db)?
1261        {
1262            let item = item.into_active_model();
1263            let key = get_key_from_active_model(&right.from_col, &item)?;
1264            leftover.push((item, key));
1265        }
1266    }
1267    let leftover = leftover; // un-mut
1268
1269    let mut via_models = Vec::new();
1270    let mut all_keys = std::collections::HashSet::new();
1271
1272    for related_model in related_models {
1273        let mut via: J::ActiveModel = ActiveModelBehavior::new();
1274        via.set_parent_key_for_def(model, &left)?;
1275        via.set_parent_key_for_def(related_model, &right)?;
1276        let via_key = get_key_from_active_model(&right.from_col, &via)?;
1277        if !leftover.iter().any(|t| t.1 == via_key) {
1278            // if not already exist, save for insert
1279            via_models.push(via);
1280        }
1281        if delete_leftover {
1282            all_keys.insert(via_key);
1283        }
1284    }
1285
1286    if delete_leftover {
1287        let mut to_delete = Vec::new();
1288        let mut to_delete_am = Vec::new();
1289        for (leftover, key) in leftover {
1290            if !all_keys.contains(&key) {
1291                to_delete.push(
1292                    leftover
1293                        .get_primary_key_value()
1294                        .expect("item is a full model"),
1295                );
1296                to_delete_am.push(leftover);
1297            }
1298        }
1299        if !to_delete.is_empty() {
1300            // run before_delete hooks
1301            for am in to_delete_am.clone() {
1302                am.before_delete(db)?;
1303            }
1304            if db.support_returning() {
1305                let deleted = J::delete_many()
1306                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
1307                    .exec_with_returning(db)?;
1308                // run after_delete hooks with the returned value if possible
1309                for am in deleted {
1310                    let am = am.into_active_model();
1311                    let _ = am.after_delete(db)?;
1312                }
1313            } else {
1314                J::delete_many()
1315                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
1316                    .exec(db)?;
1317                // fall back to the saved values if returning is not supported
1318                for am in to_delete_am {
1319                    let _ = am.after_delete(db)?;
1320                }
1321            }
1322        }
1323    }
1324
1325    if !via_models.is_empty() {
1326        // run the before_save hooks
1327        let mut via_models_res = Vec::with_capacity(via_models.len());
1328        for am in via_models {
1329            let am = am.before_save(db, true)?;
1330            via_models_res.push(am);
1331        }
1332
1333        // insert new junctions
1334        if db.support_returning() {
1335            // use the returned value if it is supported
1336            let res = J::insert_many(via_models_res)
1337                .on_conflict_do_nothing()
1338                .exec_with_returning_many(db)?;
1339            // run after_save hooks
1340            if let TryInsertResult::Inserted(inserted) = res {
1341                for model in inserted {
1342                    let _ = J::ActiveModel::after_save(model, db, true)?;
1343                }
1344            }
1345        } else {
1346            // fall back to individual inserts if returning is not supported
1347            for model in via_models_res {
1348                let res = J::insert(model)
1349                    .on_conflict_do_nothing()
1350                    .exec_with_returning(db)?;
1351                if let TryInsertResult::Inserted(model) = res {
1352                    let _ = J::ActiveModel::after_save(model, db, true)?;
1353                }
1354            }
1355        }
1356    }
1357
1358    Ok(())
1359}
1360
1361#[cfg(test)]
1362mod tests {
1363    use crate::{DbErr, entity::*, tests_cfg::*};
1364    use pretty_assertions::assert_eq;
1365
1366    #[cfg(feature = "with-json")]
1367    use serde_json::json;
1368
1369    #[test]
1370    #[cfg(feature = "macros")]
1371    fn test_derive_into_active_model_1() {
1372        mod my_fruit {
1373            pub use super::fruit::*;
1374            use crate as sea_orm;
1375            use crate::entity::prelude::*;
1376
1377            #[derive(DeriveIntoActiveModel)]
1378            pub struct NewFruit {
1379                // id is omitted
1380                pub name: String,
1381                // it is required as opposed to optional in Model
1382                pub cake_id: i32,
1383            }
1384        }
1385
1386        assert_eq!(
1387            my_fruit::NewFruit {
1388                name: "Apple".to_owned(),
1389                cake_id: 1,
1390            }
1391            .into_active_model(),
1392            fruit::ActiveModel {
1393                id: NotSet,
1394                name: Set("Apple".to_owned()),
1395                cake_id: Set(Some(1)),
1396            }
1397        );
1398    }
1399
1400    #[test]
1401    #[cfg(feature = "macros")]
1402    fn test_derive_into_active_model_2() {
1403        use crate as sea_orm;
1404        use crate::entity::prelude::*;
1405
1406        #[derive(DeriveIntoActiveModel)]
1407        #[sea_orm(active_model = "fruit::ActiveModel")]
1408        struct RequiredFruitName {
1409            name: String,
1410        }
1411
1412        assert_eq!(
1413            RequiredFruitName {
1414                name: "Apple Pie".to_owned(),
1415            }
1416            .into_active_model(),
1417            fruit::ActiveModel {
1418                id: NotSet,
1419                name: Set("Apple Pie".to_owned()),
1420                cake_id: NotSet,
1421            }
1422        );
1423
1424        #[derive(DeriveIntoActiveModel)]
1425        #[sea_orm(active_model = "fruit::ActiveModel")]
1426        struct OptionalFruitName {
1427            name: Option<String>,
1428        }
1429
1430        assert_eq!(
1431            OptionalFruitName {
1432                name: Some("Apple Pie".to_owned()),
1433            }
1434            .into_active_model(),
1435            fruit::ActiveModel {
1436                id: NotSet,
1437                name: Set("Apple Pie".to_owned()),
1438                cake_id: NotSet,
1439            }
1440        );
1441
1442        assert_eq!(
1443            OptionalFruitName { name: None }.into_active_model(),
1444            fruit::ActiveModel {
1445                id: NotSet,
1446                name: NotSet,
1447                cake_id: NotSet,
1448            }
1449        );
1450
1451        #[derive(DeriveIntoActiveModel)]
1452        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1453        struct RequiredAndNotNullFruitCake {
1454            cake_id: i32,
1455        }
1456
1457        assert_eq!(
1458            RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
1459            fruit::ActiveModel {
1460                id: NotSet,
1461                name: NotSet,
1462                cake_id: Set(Some(1)),
1463            }
1464        );
1465
1466        #[derive(DeriveIntoActiveModel)]
1467        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1468        struct OptionalAndNotNullFruitCake {
1469            cake_id: Option<i32>,
1470        }
1471
1472        assert_eq!(
1473            OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
1474            fruit::ActiveModel {
1475                id: NotSet,
1476                name: NotSet,
1477                cake_id: Set(Some(1)),
1478            }
1479        );
1480
1481        assert_eq!(
1482            OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
1483            fruit::ActiveModel {
1484                id: NotSet,
1485                name: NotSet,
1486                cake_id: NotSet,
1487            }
1488        );
1489
1490        #[derive(DeriveIntoActiveModel)]
1491        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
1492        struct OptionalAndNullableFruitCake {
1493            cake_id: Option<Option<i32>>,
1494        }
1495
1496        assert_eq!(
1497            OptionalAndNullableFruitCake {
1498                cake_id: Some(Some(1)),
1499            }
1500            .into_active_model(),
1501            fruit::ActiveModel {
1502                id: NotSet,
1503                name: NotSet,
1504                cake_id: Set(Some(1)),
1505            }
1506        );
1507
1508        assert_eq!(
1509            OptionalAndNullableFruitCake {
1510                cake_id: Some(None),
1511            }
1512            .into_active_model(),
1513            fruit::ActiveModel {
1514                id: NotSet,
1515                name: NotSet,
1516                cake_id: Set(None),
1517            }
1518        );
1519
1520        assert_eq!(
1521            OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
1522            fruit::ActiveModel {
1523                id: NotSet,
1524                name: NotSet,
1525                cake_id: NotSet,
1526            }
1527        );
1528    }
1529
1530    #[test]
1531    #[cfg(feature = "macros")]
1532    fn test_derive_into_active_model_set_single() {
1533        use crate as sea_orm;
1534        use crate::entity::prelude::*;
1535
1536        #[derive(DeriveIntoActiveModel)]
1537        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
1538        struct NewFruit {
1539            name: String,
1540        }
1541
1542        assert_eq!(
1543            NewFruit {
1544                name: "Apple".to_owned(),
1545            }
1546            .into_active_model(),
1547            fruit::ActiveModel {
1548                id: NotSet,
1549                name: Set("Apple".to_owned()),
1550                cake_id: Set(None),
1551            }
1552        );
1553    }
1554
1555    #[test]
1556    #[cfg(feature = "macros")]
1557    fn test_derive_into_active_model_set_multiple() {
1558        use crate as sea_orm;
1559        use crate::entity::prelude::*;
1560
1561        #[derive(DeriveIntoActiveModel)]
1562        #[sea_orm(
1563            active_model = "fruit::ActiveModel",
1564            set(name = "String::from(\"cherry\")", cake_id = "None")
1565        )]
1566        struct IdOnlyFruit {
1567            id: i32,
1568        }
1569        assert_eq!(
1570            IdOnlyFruit { id: 1 }.into_active_model(),
1571            fruit::ActiveModel {
1572                id: Set(1),
1573                name: Set("cherry".to_owned()),
1574                cake_id: Set(None),
1575            }
1576        );
1577
1578        #[derive(DeriveIntoActiveModel)]
1579        #[sea_orm(
1580            active_model = "fruit::ActiveModel",
1581            set(name = "String::from(\"cherry\")"),
1582            set(cake_id = "None")
1583        )]
1584        struct IdOnlyFruit2 {
1585            id: i32,
1586        }
1587        assert_eq!(
1588            IdOnlyFruit2 { id: 1 }.into_active_model(),
1589            fruit::ActiveModel {
1590                id: Set(1),
1591                name: Set("cherry".to_owned()),
1592                cake_id: Set(None),
1593            }
1594        );
1595    }
1596
1597    #[test]
1598    #[cfg(feature = "macros")]
1599    fn test_derive_into_active_model_set_separate_attrs() {
1600        use crate as sea_orm;
1601        use crate::entity::prelude::*;
1602
1603        #[derive(DeriveIntoActiveModel)]
1604        #[sea_orm(
1605            active_model = "fruit::ActiveModel",
1606            set(name = "String::from(\"cherry\")")
1607        )]
1608        #[sea_orm(set(cake_id = "None"))]
1609        struct IdOnlyFruit {
1610            id: i32,
1611        }
1612
1613        assert_eq!(
1614            IdOnlyFruit { id: 1 }.into_active_model(),
1615            fruit::ActiveModel {
1616                id: Set(1),
1617                name: Set("cherry".to_owned()),
1618                cake_id: Set(None),
1619            }
1620        );
1621    }
1622
1623    #[test]
1624    #[cfg(feature = "macros")]
1625    fn test_derive_into_active_model_ignore() {
1626        use crate as sea_orm;
1627        use crate::entity::prelude::*;
1628
1629        #[derive(DeriveIntoActiveModel)]
1630        #[sea_orm(active_model = "fruit::ActiveModel")]
1631        struct NewFruit {
1632            name: String,
1633            cake_id: i32,
1634            #[sea_orm(ignore)]
1635            _extra: String,
1636        }
1637
1638        assert_eq!(
1639            NewFruit {
1640                name: "Apple".to_owned(),
1641                cake_id: 1,
1642                _extra: "ignored".to_owned(),
1643            }
1644            .into_active_model(),
1645            fruit::ActiveModel {
1646                id: NotSet,
1647                name: Set("Apple".to_owned()),
1648                cake_id: Set(Some(1)),
1649            }
1650        );
1651    }
1652
1653    #[test]
1654    #[cfg(feature = "macros")]
1655    fn test_derive_into_active_model_skip() {
1656        use crate as sea_orm;
1657        use crate::entity::prelude::*;
1658
1659        #[derive(DeriveIntoActiveModel)]
1660        #[sea_orm(active_model = "fruit::ActiveModel")]
1661        struct NewFruit {
1662            name: String,
1663            #[sea_orm(skip)]
1664            _extra: String,
1665        }
1666
1667        assert_eq!(
1668            NewFruit {
1669                name: "Apple".to_owned(),
1670                _extra: "skipped".to_owned(),
1671            }
1672            .into_active_model(),
1673            fruit::ActiveModel {
1674                id: NotSet,
1675                name: Set("Apple".to_owned()),
1676                cake_id: NotSet,
1677            }
1678        );
1679    }
1680
1681    #[test]
1682    #[cfg(feature = "macros")]
1683    fn test_derive_into_active_model_set_and_ignore() {
1684        use crate as sea_orm;
1685        use crate::entity::prelude::*;
1686
1687        #[derive(DeriveIntoActiveModel)]
1688        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
1689        struct NewFruit {
1690            name: String,
1691            #[sea_orm(ignore)]
1692            _extra: String,
1693        }
1694
1695        assert_eq!(
1696            NewFruit {
1697                name: "Apple".to_owned(),
1698                _extra: "ignored".to_owned(),
1699            }
1700            .into_active_model(),
1701            fruit::ActiveModel {
1702                id: NotSet,
1703                name: Set("Apple".to_owned()),
1704                cake_id: Set(Some(42)),
1705            }
1706        );
1707    }
1708
1709    #[test]
1710    #[cfg(feature = "macros")]
1711    fn test_derive_into_active_model_foreign_ignore() {
1712        use serde::{Deserialize, Serialize};
1713
1714        use crate as sea_orm;
1715        use crate::entity::prelude::*;
1716
1717        #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
1718        #[sea_orm(active_model = "fruit::ActiveModel")]
1719        struct NewFruit {
1720            #[sea_orm(ignore)]
1721            id: i32,
1722            name: String,
1723            #[serde(skip)]
1724            cake_id: Option<i32>,
1725        }
1726
1727        assert_eq!(
1728            NewFruit {
1729                id: 1.to_owned(),
1730                name: "Apple".to_owned(),
1731                cake_id: Some(42)
1732            }
1733            .into_active_model(),
1734            fruit::ActiveModel {
1735                id: NotSet,
1736                name: Set("Apple".to_owned()),
1737                cake_id: Set(Some(42)),
1738            }
1739        );
1740    }
1741
1742    #[test]
1743    #[cfg(feature = "macros")]
1744    fn test_derive_into_active_model_exhaustive() {
1745        use crate as sea_orm;
1746        use crate::entity::prelude::*;
1747
1748        #[derive(DeriveIntoActiveModel)]
1749        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1750        struct FullFruit {
1751            id: i32,
1752            name: String,
1753        }
1754
1755        assert_eq!(
1756            FullFruit {
1757                id: 1,
1758                name: "Apple".to_owned(),
1759            }
1760            .into_active_model(),
1761            fruit::ActiveModel {
1762                id: Set(1),
1763                name: Set("Apple".to_owned()),
1764                cake_id: Set(None),
1765            }
1766        );
1767    }
1768
1769    #[test]
1770    #[cfg(feature = "macros")]
1771    fn test_derive_into_active_model_multiple_sets() {
1772        use crate as sea_orm;
1773        use crate::entity::prelude::*;
1774
1775        const DEFULT_CAKE_ID: i32 = 1;
1776        #[derive(DeriveIntoActiveModel)]
1777        #[sea_orm(
1778            active_model = "fruit::ActiveModel",
1779            exhaustive,
1780            set(cake_id = "Some(DEFULT_CAKE_ID)")
1781        )]
1782        struct FullFruit {
1783            id: i32,
1784            name: String,
1785        }
1786
1787        assert_eq!(
1788            FullFruit {
1789                id: 1,
1790                name: "Apple".to_owned(),
1791            }
1792            .into_active_model(),
1793            fruit::ActiveModel {
1794                id: Set(1),
1795                name: Set("Apple".to_owned()),
1796                cake_id: Set(Some(1)),
1797            }
1798        );
1799    }
1800
1801    #[test]
1802    #[cfg(feature = "macros")]
1803    fn test_derive_into_active_model_field_empty_default() {
1804        use crate as sea_orm;
1805        use crate::entity::prelude::*;
1806
1807        #[derive(DeriveIntoActiveModel)]
1808        #[sea_orm(active_model = "fruit::ActiveModel")]
1809        struct NewFruit {
1810            #[sea_orm(default)]
1811            name: Option<String>,
1812        }
1813
1814        // Some(v) -> Set(v)
1815        assert_eq!(
1816            NewFruit {
1817                name: Some("Apple".to_owned()),
1818            }
1819            .into_active_model(),
1820            fruit::ActiveModel {
1821                id: NotSet,
1822                name: Set("Apple".to_owned()),
1823                cake_id: NotSet,
1824            }
1825        );
1826
1827        // None -> Set(fallback)
1828        assert_eq!(
1829            NewFruit { name: None }.into_active_model(),
1830            fruit::ActiveModel {
1831                id: NotSet,
1832                name: Set("".to_owned()),
1833                cake_id: NotSet,
1834            }
1835        );
1836    }
1837
1838    #[test]
1839    #[cfg(feature = "macros")]
1840    fn test_derive_into_active_model_field_custom_option() {
1841        use crate as sea_orm;
1842        use crate::entity::prelude::*;
1843        mod foreign_crate {
1844            #[derive(Debug, Clone, PartialEq, Eq)]
1845            pub enum CustomOption<T> {
1846                None,
1847                Some(T),
1848            }
1849
1850            impl From<CustomOption<String>> for Option<String> {
1851                fn from(option: CustomOption<String>) -> Self {
1852                    match option {
1853                        CustomOption::None => Option::None,
1854                        CustomOption::Some(value) => value.into(),
1855                    }
1856                }
1857            }
1858        }
1859        use foreign_crate::CustomOption;
1860
1861        #[derive(DeriveIntoActiveModel)]
1862        #[sea_orm(active_model = "fruit::ActiveModel")]
1863        struct NewFruit {
1864            #[sea_orm(default)]
1865            name: CustomOption<String>,
1866        }
1867
1868        // Some(v) -> Set(v)
1869        assert_eq!(
1870            NewFruit {
1871                name: CustomOption::Some("Apple".to_owned()),
1872            }
1873            .into_active_model(),
1874            fruit::ActiveModel {
1875                id: NotSet,
1876                name: Set("Apple".to_owned()),
1877                cake_id: NotSet,
1878            }
1879        );
1880
1881        // None -> Set(fallback)
1882        assert_eq!(
1883            NewFruit {
1884                name: CustomOption::None
1885            }
1886            .into_active_model(),
1887            fruit::ActiveModel {
1888                id: NotSet,
1889                name: Set("".to_owned()),
1890                cake_id: NotSet,
1891            }
1892        );
1893    }
1894
1895    #[test]
1896    #[cfg(feature = "macros")]
1897    fn test_derive_into_active_model_field_default_some() {
1898        use crate as sea_orm;
1899        use crate::entity::prelude::*;
1900
1901        #[derive(DeriveIntoActiveModel)]
1902        #[sea_orm(active_model = "fruit::ActiveModel")]
1903        struct NewFruit {
1904            #[sea_orm(default = "String::from(\"Unnamed\")")]
1905            name: Option<String>,
1906        }
1907
1908        // Some(v) -> Set(v)
1909        assert_eq!(
1910            NewFruit {
1911                name: Some("Apple".to_owned()),
1912            }
1913            .into_active_model(),
1914            fruit::ActiveModel {
1915                id: NotSet,
1916                name: Set("Apple".to_owned()),
1917                cake_id: NotSet,
1918            }
1919        );
1920
1921        // None -> Set(fallback)
1922        assert_eq!(
1923            NewFruit { name: None }.into_active_model(),
1924            fruit::ActiveModel {
1925                id: NotSet,
1926                name: Set("Unnamed".to_owned()),
1927                cake_id: NotSet,
1928            }
1929        );
1930    }
1931
1932    #[test]
1933    #[cfg(feature = "macros")]
1934    fn test_derive_into_active_model_field_default_with_set() {
1935        use crate as sea_orm;
1936        use crate::entity::prelude::*;
1937
1938        #[derive(DeriveIntoActiveModel)]
1939        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
1940        struct NewFruit {
1941            #[sea_orm(default = "String::from(\"Unnamed\")")]
1942            name: Option<String>,
1943            #[sea_orm(ignore)]
1944            _extra: String,
1945        }
1946
1947        assert_eq!(
1948            NewFruit {
1949                name: Some("Apple".to_owned()),
1950                _extra: "ignored".to_owned(),
1951            }
1952            .into_active_model(),
1953            fruit::ActiveModel {
1954                id: NotSet,
1955                name: Set("Apple".to_owned()),
1956                cake_id: Set(Some(99)),
1957            }
1958        );
1959
1960        assert_eq!(
1961            NewFruit {
1962                name: None,
1963                _extra: "ignored".to_owned(),
1964            }
1965            .into_active_model(),
1966            fruit::ActiveModel {
1967                id: NotSet,
1968                name: Set("Unnamed".to_owned()),
1969                cake_id: Set(Some(99)),
1970            }
1971        );
1972    }
1973
1974    #[test]
1975    #[cfg(feature = "macros")]
1976    fn test_derive_into_active_model_field_default_exhaustive() {
1977        use crate as sea_orm;
1978        use crate::entity::prelude::*;
1979
1980        #[derive(DeriveIntoActiveModel)]
1981        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
1982        struct NewFruit {
1983            id: i32,
1984            #[sea_orm(default = "String::from(\"Unnamed\")")]
1985            name: Option<String>,
1986        }
1987
1988        assert_eq!(
1989            NewFruit {
1990                id: 1,
1991                name: Some("Apple".to_owned()),
1992            }
1993            .into_active_model(),
1994            fruit::ActiveModel {
1995                id: Set(1),
1996                name: Set("Apple".to_owned()),
1997                cake_id: Set(None),
1998            }
1999        );
2000
2001        assert_eq!(
2002            NewFruit { id: 2, name: None }.into_active_model(),
2003            fruit::ActiveModel {
2004                id: Set(2),
2005                name: Set("Unnamed".to_owned()),
2006                cake_id: Set(None),
2007            }
2008        );
2009    }
2010
2011    #[test]
2012    #[cfg(feature = "macros")]
2013    fn test_derive_try_into_model_1() {
2014        mod my_fruit {
2015            use crate as sea_orm;
2016            use crate::entity::prelude::*;
2017
2018            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2019            #[sea_orm(table_name = "fruit")]
2020            pub struct Model {
2021                #[sea_orm(primary_key)]
2022                pub id: i32,
2023                pub name: String,
2024                pub cake_id: Option<i32>,
2025            }
2026
2027            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2028            pub enum Relation {}
2029
2030            impl ActiveModelBehavior for ActiveModel {}
2031        }
2032        assert_eq!(
2033            my_fruit::ActiveModel {
2034                id: Set(1),
2035                name: Set("Pineapple".to_owned()),
2036                cake_id: Set(None),
2037            }
2038            .try_into_model()
2039            .unwrap(),
2040            my_fruit::Model {
2041                id: 1,
2042                name: "Pineapple".to_owned(),
2043                cake_id: None,
2044            }
2045        );
2046
2047        assert_eq!(
2048            my_fruit::ActiveModel {
2049                id: Set(2),
2050                name: Set("Apple".to_owned()),
2051                cake_id: Set(Some(1)),
2052            }
2053            .try_into_model()
2054            .unwrap(),
2055            my_fruit::Model {
2056                id: 2,
2057                name: "Apple".to_owned(),
2058                cake_id: Some(1),
2059            }
2060        );
2061
2062        assert_eq!(
2063            my_fruit::ActiveModel {
2064                id: Set(1),
2065                name: NotSet,
2066                cake_id: Set(None),
2067            }
2068            .try_into_model(),
2069            Err(DbErr::AttrNotSet(String::from("name")))
2070        );
2071
2072        assert_eq!(
2073            my_fruit::ActiveModel {
2074                id: Set(1),
2075                name: Set("Pineapple".to_owned()),
2076                cake_id: NotSet,
2077            }
2078            .try_into_model(),
2079            Err(DbErr::AttrNotSet(String::from("cake_id")))
2080        );
2081    }
2082
2083    #[test]
2084    #[cfg(feature = "macros")]
2085    fn test_derive_try_into_model_2() {
2086        mod my_fruit {
2087            use crate as sea_orm;
2088            use crate::entity::prelude::*;
2089
2090            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2091            #[sea_orm(table_name = "fruit")]
2092            pub struct Model {
2093                #[sea_orm(primary_key)]
2094                pub id: i32,
2095                pub name: String,
2096                #[sea_orm(ignore)]
2097                pub cake_id: Option<i32>,
2098            }
2099
2100            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2101            pub enum Relation {}
2102
2103            impl ActiveModelBehavior for ActiveModel {}
2104        }
2105        assert_eq!(
2106            my_fruit::ActiveModel {
2107                id: Set(1),
2108                name: Set("Pineapple".to_owned()),
2109            }
2110            .try_into_model()
2111            .unwrap(),
2112            my_fruit::Model {
2113                id: 1,
2114                name: "Pineapple".to_owned(),
2115                cake_id: None,
2116            }
2117        );
2118    }
2119
2120    #[test]
2121    #[cfg(feature = "macros")]
2122    fn test_derive_try_into_model_3() {
2123        mod my_fruit {
2124            use crate as sea_orm;
2125            use crate::entity::prelude::*;
2126
2127            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
2128            #[sea_orm(table_name = "fruit")]
2129            pub struct Model {
2130                #[sea_orm(primary_key)]
2131                pub id: i32,
2132                #[sea_orm(ignore)]
2133                pub name: String,
2134                pub cake_id: Option<i32>,
2135            }
2136
2137            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
2138            pub enum Relation {}
2139
2140            impl ActiveModelBehavior for ActiveModel {}
2141        }
2142        assert_eq!(
2143            my_fruit::ActiveModel {
2144                id: Set(1),
2145                cake_id: Set(Some(1)),
2146            }
2147            .try_into_model()
2148            .unwrap(),
2149            my_fruit::Model {
2150                id: 1,
2151                name: "".to_owned(),
2152                cake_id: Some(1),
2153            }
2154        );
2155    }
2156
2157    #[test]
2158    #[cfg(feature = "with-json")]
2159    fn test_active_model_set_from_json_1() {
2160        assert_eq!(
2161            cake::ActiveModel::from_json(json!({
2162                "id": 1,
2163                "name": "Apple Pie",
2164            }))
2165            .unwrap(),
2166            cake::ActiveModel {
2167                id: Set(1),
2168                name: Set("Apple Pie".to_owned()),
2169            }
2170        );
2171
2172        assert_eq!(
2173            cake::ActiveModel::from_json(json!({
2174                "id": 1,
2175            }))
2176            .unwrap(),
2177            cake::ActiveModel {
2178                id: Set(1),
2179                name: NotSet,
2180            }
2181        );
2182
2183        assert_eq!(
2184            cake::ActiveModel::from_json(json!({
2185                "name": "Apple Pie",
2186            }))
2187            .unwrap(),
2188            cake::ActiveModel {
2189                id: NotSet,
2190                name: Set("Apple Pie".to_owned()),
2191            }
2192        );
2193
2194        let mut cake: cake::ActiveModel = Default::default();
2195        cake.set_from_json(json!({
2196            "name": "Apple Pie",
2197        }))
2198        .unwrap();
2199        assert_eq!(
2200            cake,
2201            cake::ActiveModel {
2202                id: NotSet,
2203                name: Set("Apple Pie".to_owned()),
2204            }
2205        );
2206    }
2207
2208    #[test]
2209    #[cfg(feature = "with-json")]
2210    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
2211        let mut fruit: fruit::ActiveModel = Default::default();
2212
2213        fruit.set_from_json(json!({
2214            "name": "Apple",
2215        }))?;
2216        assert_eq!(
2217            fruit,
2218            fruit::ActiveModel {
2219                id: ActiveValue::NotSet,
2220                name: ActiveValue::Set("Apple".to_owned()),
2221                cake_id: ActiveValue::NotSet,
2222            }
2223        );
2224
2225        assert_eq!(
2226            fruit::ActiveModel::from_json(json!({
2227                "name": "Apple",
2228            }))?,
2229            fruit::ActiveModel {
2230                id: ActiveValue::NotSet,
2231                name: ActiveValue::Set("Apple".to_owned()),
2232                cake_id: ActiveValue::NotSet,
2233            }
2234        );
2235
2236        fruit.set_from_json(json!({
2237            "name": "Apple",
2238            "cake_id": null,
2239        }))?;
2240        assert_eq!(
2241            fruit,
2242            fruit::ActiveModel {
2243                id: ActiveValue::NotSet,
2244                name: ActiveValue::Set("Apple".to_owned()),
2245                cake_id: ActiveValue::Set(None),
2246            }
2247        );
2248
2249        fruit.set_from_json(json!({
2250            "id": null,
2251            "name": "Apple",
2252            "cake_id": 1,
2253        }))?;
2254        assert_eq!(
2255            fruit,
2256            fruit::ActiveModel {
2257                id: ActiveValue::NotSet,
2258                name: ActiveValue::Set("Apple".to_owned()),
2259                cake_id: ActiveValue::Set(Some(1)),
2260            }
2261        );
2262
2263        fruit.set_from_json(json!({
2264            "id": 2,
2265            "name": "Apple",
2266            "cake_id": 1,
2267        }))?;
2268        assert_eq!(
2269            fruit,
2270            fruit::ActiveModel {
2271                id: ActiveValue::NotSet,
2272                name: ActiveValue::Set("Apple".to_owned()),
2273                cake_id: ActiveValue::Set(Some(1)),
2274            }
2275        );
2276
2277        let mut fruit = fruit::ActiveModel {
2278            id: ActiveValue::Set(1),
2279            name: ActiveValue::NotSet,
2280            cake_id: ActiveValue::NotSet,
2281        };
2282        fruit.set_from_json(json!({
2283            "id": 8,
2284            "name": "Apple",
2285            "cake_id": 1,
2286        }))?;
2287        assert_eq!(
2288            fruit,
2289            fruit::ActiveModel {
2290                id: ActiveValue::Set(1),
2291                name: ActiveValue::Set("Apple".to_owned()),
2292                cake_id: ActiveValue::Set(Some(1)),
2293            }
2294        );
2295
2296        Ok(())
2297    }
2298
2299    #[test]
2300    #[cfg(feature = "with-json")]
2301    fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
2302        use crate::*;
2303
2304        let db = MockDatabase::new(DbBackend::Postgres)
2305            .append_exec_results([
2306                MockExecResult {
2307                    last_insert_id: 1,
2308                    rows_affected: 1,
2309                },
2310                MockExecResult {
2311                    last_insert_id: 1,
2312                    rows_affected: 1,
2313                },
2314            ])
2315            .append_query_results([
2316                [fruit::Model {
2317                    id: 1,
2318                    name: "Apple".to_owned(),
2319                    cake_id: None,
2320                }],
2321                [fruit::Model {
2322                    id: 2,
2323                    name: "Orange".to_owned(),
2324                    cake_id: Some(1),
2325                }],
2326            ])
2327            .into_connection();
2328
2329        let mut fruit: fruit::ActiveModel = Default::default();
2330        fruit.set_from_json(json!({
2331            "name": "Apple",
2332        }))?;
2333        fruit.save(&db)?;
2334
2335        let mut fruit = fruit::ActiveModel {
2336            id: Set(2),
2337            ..Default::default()
2338        };
2339        fruit.set_from_json(json!({
2340            "id": 9,
2341            "name": "Orange",
2342            "cake_id": 1,
2343        }))?;
2344        fruit.save(&db)?;
2345
2346        assert_eq!(
2347            db.into_transaction_log(),
2348            [
2349                Transaction::from_sql_and_values(
2350                    DbBackend::Postgres,
2351                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
2352                    ["Apple".into()],
2353                ),
2354                Transaction::from_sql_and_values(
2355                    DbBackend::Postgres,
2356                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2357                    ["Orange".into(), 1i32.into(), 2i32.into()],
2358                ),
2359            ]
2360        );
2361
2362        Ok(())
2363    }
2364
2365    #[test]
2366    fn test_active_model_is_changed() {
2367        let mut fruit: fruit::ActiveModel = Default::default();
2368        assert!(!fruit.is_changed());
2369
2370        fruit.set(fruit::Column::Name, "apple".into());
2371        assert!(fruit.is_changed());
2372
2373        let mut fruit = fruit::Model {
2374            id: 1,
2375            name: "".into(),
2376            cake_id: None,
2377        };
2378        fruit.set("name".parse().unwrap(), "orange".into());
2379        assert_eq!(fruit.name, "orange");
2380    }
2381
2382    #[test]
2383    fn test_reset_1() {
2384        assert_eq!(
2385            fruit::Model {
2386                id: 1,
2387                name: "Apple".into(),
2388                cake_id: None,
2389            }
2390            .into_active_model(),
2391            fruit::ActiveModel {
2392                id: Unchanged(1),
2393                name: Unchanged("Apple".into()),
2394                cake_id: Unchanged(None)
2395            },
2396        );
2397
2398        assert_eq!(
2399            fruit::Model {
2400                id: 1,
2401                name: "Apple".into(),
2402                cake_id: None,
2403            }
2404            .into_active_model()
2405            .reset_all(),
2406            fruit::ActiveModel {
2407                id: Set(1),
2408                name: Set("Apple".into()),
2409                cake_id: Set(None)
2410            },
2411        );
2412
2413        assert_eq!(
2414            fruit::Model {
2415                id: 1,
2416                name: "Apple".into(),
2417                cake_id: Some(2),
2418            }
2419            .into_active_model(),
2420            fruit::ActiveModel {
2421                id: Unchanged(1),
2422                name: Unchanged("Apple".into()),
2423                cake_id: Unchanged(Some(2)),
2424            },
2425        );
2426
2427        assert_eq!(
2428            fruit::Model {
2429                id: 1,
2430                name: "Apple".into(),
2431                cake_id: Some(2),
2432            }
2433            .into_active_model()
2434            .reset_all(),
2435            fruit::ActiveModel {
2436                id: Set(1),
2437                name: Set("Apple".into()),
2438                cake_id: Set(Some(2)),
2439            },
2440        );
2441    }
2442
2443    #[test]
2444    fn test_reset_2() -> Result<(), DbErr> {
2445        use crate::*;
2446
2447        let db = MockDatabase::new(DbBackend::Postgres)
2448            .append_exec_results(vec![
2449                MockExecResult {
2450                    last_insert_id: 1,
2451                    rows_affected: 1,
2452                },
2453                MockExecResult {
2454                    last_insert_id: 1,
2455                    rows_affected: 1,
2456                },
2457            ])
2458            .append_query_results(vec![
2459                vec![fruit::Model {
2460                    id: 1,
2461                    name: "Apple".to_owned(),
2462                    cake_id: None,
2463                }],
2464                vec![fruit::Model {
2465                    id: 1,
2466                    name: "Apple".to_owned(),
2467                    cake_id: None,
2468                }],
2469            ])
2470            .into_connection();
2471
2472        fruit::Model {
2473            id: 1,
2474            name: "Apple".into(),
2475            cake_id: None,
2476        }
2477        .into_active_model()
2478        .update(&db)?;
2479
2480        fruit::Model {
2481            id: 1,
2482            name: "Apple".into(),
2483            cake_id: None,
2484        }
2485        .into_active_model()
2486        .reset_all()
2487        .update(&db)?;
2488
2489        assert_eq!(
2490            db.into_transaction_log(),
2491            vec![
2492                Transaction::from_sql_and_values(
2493                    DbBackend::Postgres,
2494                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
2495                    vec![1i32.into(), 1u64.into()],
2496                ),
2497                Transaction::from_sql_and_values(
2498                    DbBackend::Postgres,
2499                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
2500                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
2501                ),
2502            ]
2503        );
2504
2505        Ok(())
2506    }
2507
2508    #[test]
2509    fn test_active_model_default_values() {
2510        assert_eq!(
2511            fruit::ActiveModel::default_values(),
2512            fruit::ActiveModel {
2513                id: Set(0),
2514                name: Set("".into()),
2515                cake_id: Set(None),
2516            },
2517        );
2518
2519        assert_eq!(
2520            lunch_set::ActiveModel::default_values(),
2521            lunch_set::ActiveModel {
2522                id: Set(0),
2523                name: Set("".into()),
2524                tea: NotSet,
2525            },
2526        );
2527    }
2528
2529    #[test]
2530    fn test_active_model_set_parent_key() {
2531        let mut fruit = fruit::Model {
2532            id: 2,
2533            name: "F".into(),
2534            cake_id: None,
2535        }
2536        .into_active_model();
2537
2538        let cake = cake::Model {
2539            id: 4,
2540            name: "C".into(),
2541        }
2542        .into_active_model();
2543
2544        fruit.set_parent_key(&cake).unwrap();
2545
2546        assert_eq!(
2547            fruit,
2548            fruit::ActiveModel {
2549                id: Unchanged(2),
2550                name: Unchanged("F".into()),
2551                cake_id: Set(Some(4)),
2552            }
2553        );
2554
2555        assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());
2556
2557        assert_eq!(
2558            fruit,
2559            fruit::ActiveModel {
2560                id: Unchanged(2),
2561                name: Unchanged("F".into()),
2562                cake_id: Set(None),
2563            }
2564        );
2565
2566        let mut cake_filling = cake_filling::ActiveModel::new();
2567
2568        cake_filling.set_parent_key(&cake).unwrap();
2569
2570        assert_eq!(
2571            cake_filling,
2572            cake_filling::ActiveModel {
2573                cake_id: Set(4),
2574                filling_id: NotSet,
2575            }
2576        );
2577    }
2578}