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