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