use super::{ActiveValue, ActiveValue::*};
use crate::{
    ColumnTrait, Condition, ConnectionTrait, DbBackend, DeleteResult, EntityName, EntityTrait,
    IdenStatic, Iterable, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter,
    Related, RelatedSelfVia, RelationDef, RelationTrait, TryInsertResult, UpdateResult, Value,
    error::*,
    query::{
        clear_key_on_active_model, column_tuple_in_condition, get_key_from_active_model,
        set_key_on_active_model,
    },
};
use sea_query::ValueTuple;
use std::fmt::Debug;

/// The editable counterpart of a [`Model`](crate::ModelTrait), used to build
/// `INSERT` and `UPDATE` statements.
///
/// Each field of an ActiveModel is wrapped in an [`ActiveValue`], so it can
/// be one of:
///
/// - [`Set(v)`](ActiveValue::Set) — a new value to write,
/// - [`Unchanged(v)`](ActiveValue::Unchanged) — the value already in the
///   database, will not be sent in `UPDATE`,
/// - [`NotSet`](ActiveValue::NotSet) — value is absent; the column is
///   omitted from `INSERT` (letting the database supply a default) and
///   from `UPDATE`.
///
/// This makes ActiveModel ideal for partial updates: only the columns you
/// touch end up in the generated `UPDATE`.
pub trait ActiveModelTrait: Clone + Debug {
    /// The [`EntityTrait`] this ActiveModel belongs to.
    type Entity: EntityTrait;

    /// Take the [`ActiveValue`] of a column, leaving it as `NotSet`.
    fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;

    /// Read the [`ActiveValue`] of a column.
    fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;

    /// Set one column to `Set(v)`. Panics on type mismatch; prefer
    /// [`try_set`](Self::try_set) when the value comes from untrusted input.
    fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) {
        self.try_set(c, v)
            .unwrap_or_else(|e| panic!("Failed to set value for {:?}: {e:?}", c.as_column_ref()))
    }

    /// Set one column to `Set(v)` only if `v` differs from the current value,
    /// avoiding spurious `UPDATE` rewrites. Panics on type mismatch.
    fn set_if_not_equals(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);

    /// Set one column to `Set(v)`, returning an error on type mismatch.
    fn try_set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value) -> Result<(), DbErr>;

    /// Mark a column as `NotSet` so it is omitted from the next `INSERT` or
    /// `UPDATE`.
    fn not_set(&mut self, c: <Self::Entity as EntityTrait>::Column);

    /// `true` if the column is currently in the `NotSet` state.
    fn is_not_set(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;

    /// A fresh ActiveModel with every column `NotSet`.
    fn default() -> Self;

    /// A fresh ActiveModel pre-populated with `Set(default_value)` for each
    /// column that has a `Default` impl; other columns remain `NotSet`.
    fn default_values() -> Self;

    /// Promote one column from [`Unchanged`](ActiveValue::Unchanged) to
    /// [`Set`](ActiveValue::Set) so it will be included in the next
    /// `UPDATE`. Leaves [`NotSet`](ActiveValue::NotSet) untouched.
    fn reset(&mut self, c: <Self::Entity as EntityTrait>::Column);

    /// Apply [`reset`](Self::reset) to every column, forcing the next
    /// `UPDATE` to write all non-`NotSet` columns.
    fn reset_all(mut self) -> Self {
        for col in <Self::Entity as EntityTrait>::Column::iter() {
            self.reset(col);
        }
        self
    }

    /// The primary key as a `ValueTuple`, or `None` if any primary-key
    /// column is still `NotSet`.
    fn get_primary_key_value(&self) -> Option<ValueTuple> {
        let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
        macro_rules! next {
            () => {
                self.get(cols.next()?.into_column()).into_value()?
            };
        }
        match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
            1 => {
                let s1 = next!();
                Some(ValueTuple::One(s1))
            }
            2 => {
                let s1 = next!();
                let s2 = next!();
                Some(ValueTuple::Two(s1, s2))
            }
            3 => {
                let s1 = next!();
                let s2 = next!();
                let s3 = next!();
                Some(ValueTuple::Three(s1, s2, s3))
            }
            len => {
                let mut vec = Vec::with_capacity(len);
                for _ in 0..len {
                    let s = next!();
                    vec.push(s);
                }
                Some(ValueTuple::Many(vec))
            }
        }
    }

    /// Perform an `INSERT` operation on the ActiveModel
    ///
    /// # Example (Postgres)
    ///
    /// ```
    /// # use sea_orm::{error::*, tests_cfg::*, *};
    /// #
    /// # #[cfg(feature = "mock")]
    /// # pub fn main() -> Result<(), DbErr> {
    /// #
    /// # let db = MockDatabase::new(DbBackend::Postgres)
    /// #     .append_query_results([
    /// #         [cake::Model {
    /// #             id: 15,
    /// #             name: "Apple Pie".to_owned(),
    /// #         }],
    /// #     ])
    /// #     .into_connection();
    /// #
    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
    ///
    /// let apple = cake::ActiveModel {
    ///     name: Set("Apple Pie".to_owned()),
    ///     ..Default::default()
    /// };
    ///
    /// assert_eq!(
    ///     apple.insert(&db)?,
    ///     cake::Model {
    ///         id: 15,
    ///         name: "Apple Pie".to_owned(),
    ///     }
    /// );
    ///
    /// assert_eq!(
    ///     db.into_transaction_log(),
    ///     [Transaction::from_sql_and_values(
    ///         DbBackend::Postgres,
    ///         r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id", "name""#,
    ///         ["Apple Pie".into()]
    ///     )]
    /// );
    /// #
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// # Example (MySQL)
    ///
    /// ```
    /// # use sea_orm::{error::*, tests_cfg::*, *};
    /// #
    /// # #[cfg(feature = "mock")]
    /// # pub fn main() -> Result<(), DbErr> {
    /// #
    /// # let db = MockDatabase::new(DbBackend::MySql)
    /// #     .append_query_results([
    /// #         [cake::Model {
    /// #             id: 15,
    /// #             name: "Apple Pie".to_owned(),
    /// #         }],
    /// #     ])
    /// #     .append_exec_results([
    /// #         MockExecResult {
    /// #             last_insert_id: 15,
    /// #             rows_affected: 1,
    /// #         },
    /// #     ])
    /// #     .into_connection();
    /// #
    /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
    ///
    /// let apple = cake::ActiveModel {
    ///     name: Set("Apple Pie".to_owned()),
    ///     ..Default::default()
    /// };
    ///
    /// assert_eq!(
    ///     apple.insert(&db)?,
    ///     cake::Model {
    ///         id: 15,
    ///         name: "Apple Pie".to_owned(),
    ///     }
    /// );
    ///
    /// assert_eq!(
    ///     db.into_transaction_log(),
    ///     [
    ///         Transaction::from_sql_and_values(
    ///             DbBackend::MySql,
    ///             r#"INSERT INTO `cake` (`name`) VALUES (?)"#,
    ///             ["Apple Pie".into()]
    ///         ),
    ///         Transaction::from_sql_and_values(
    ///             DbBackend::MySql,
    ///             r#"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = ? LIMIT ?"#,
    ///             [15.into(), 1u64.into()]
    ///         )
    ///     ]
    /// );
    /// #
    /// # Ok(())
    /// # }
    /// ```
    fn insert<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
    where
        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
        Self: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let am = ActiveModelBehavior::before_save(self, db, true)?;
        let model = <Self::Entity as EntityTrait>::insert(am).exec_with_returning(db)?;
        Self::after_save(model, db, true)
    }

    /// Perform the `UPDATE` operation on an ActiveModel
    ///
    /// # Example (Postgres)
    ///
    /// ```
    /// # use sea_orm::{error::*, tests_cfg::*, *};
    /// #
    /// # #[cfg(feature = "mock")]
    /// # pub fn main() -> Result<(), DbErr> {
    /// #
    /// # let db = MockDatabase::new(DbBackend::Postgres)
    /// #     .append_query_results([
    /// #         [fruit::Model {
    /// #             id: 1,
    /// #             name: "Orange".to_owned(),
    /// #             cake_id: None,
    /// #         }],
    /// #     ])
    /// #     .into_connection();
    /// #
    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
    ///
    /// let orange = fruit::ActiveModel {
    ///     id: Set(1),
    ///     name: Set("Orange".to_owned()),
    ///     ..Default::default()
    /// };
    ///
    /// assert_eq!(
    ///     orange.update(&db)?,
    ///     fruit::Model {
    ///         id: 1,
    ///         name: "Orange".to_owned(),
    ///         cake_id: None,
    ///     }
    /// );
    ///
    /// assert_eq!(
    ///     db.into_transaction_log(),
    ///     [Transaction::from_sql_and_values(
    ///         DbBackend::Postgres,
    ///         r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2 RETURNING "id", "name", "cake_id""#,
    ///         ["Orange".into(), 1i32.into()]
    ///     )]);
    /// #
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// # Example (MySQL)
    ///
    /// ```
    /// # use sea_orm::{error::*, tests_cfg::*, *};
    /// #
    /// # #[cfg(feature = "mock")]
    /// # pub fn main() -> Result<(), DbErr> {
    /// #
    /// # let db = MockDatabase::new(DbBackend::MySql)
    /// #     .append_query_results([
    /// #         [fruit::Model {
    /// #             id: 1,
    /// #             name: "Orange".to_owned(),
    /// #             cake_id: None,
    /// #         }],
    /// #     ])
    /// #     .append_exec_results([
    /// #         MockExecResult {
    /// #             last_insert_id: 0,
    /// #             rows_affected: 1,
    /// #         },
    /// #     ])
    /// #     .into_connection();
    /// #
    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
    ///
    /// let orange = fruit::ActiveModel {
    ///     id: Set(1),
    ///     name: Set("Orange".to_owned()),
    ///     ..Default::default()
    /// };
    ///
    /// assert_eq!(
    ///     orange.update(&db)?,
    ///     fruit::Model {
    ///         id: 1,
    ///         name: "Orange".to_owned(),
    ///         cake_id: None,
    ///     }
    /// );
    ///
    /// assert_eq!(
    ///     db.into_transaction_log(),
    ///     [
    ///         Transaction::from_sql_and_values(
    ///             DbBackend::MySql,
    ///             r#"UPDATE `fruit` SET `name` = ? WHERE `fruit`.`id` = ?"#,
    ///             ["Orange".into(), 1i32.into()]
    ///         ),
    ///         Transaction::from_sql_and_values(
    ///             DbBackend::MySql,
    ///             r#"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = ? LIMIT ?"#,
    ///             [1i32.into(), 1u64.into()]
    ///         )]);
    /// #
    /// # Ok(())
    /// # }
    /// ```
    fn update<'a, C>(self, db: &'a C) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
    where
        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
        Self: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let am = ActiveModelBehavior::before_save(self, db, false)?;
        let model: <Self::Entity as EntityTrait>::Model = Self::Entity::update(am).exec(db)?;
        Self::after_save(model, db, false)
    }

    /// Update an ActiveModel without a RETURNING clause, yielding an
    /// [`UpdateResult`] instead of the updated model. Useful on backends without
    /// RETURNING support, or when the updated model is not needed.
    ///
    /// Unlike [`ActiveModelTrait::update`], this runs
    /// [`ActiveModelBehavior::before_save`] but does **not** run
    /// [`ActiveModelBehavior::after_save`] (there is no returned model to pass to
    /// it). Returns [`DbErr::RecordNotUpdated`] if no row matches.
    fn update_without_returning<'a, C>(self, db: &'a C) -> Result<UpdateResult, DbErr>
    where
        Self: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let am = ActiveModelBehavior::before_save(self, db, false)?;
        Self::Entity::update(am).exec_without_returning(db)
    }

    /// Insert the model if primary key is `NotSet`, update otherwise.
    /// Only works if the entity has auto increment primary key.
    fn save<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
    where
        <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
        Self: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let res = if !self.is_update() {
            self.insert(db)
        } else {
            self.update(db)
        }?;
        Ok(res.into_active_model())
    }

    /// Returns true if the primary key is fully-specified
    #[doc(hidden)]
    fn is_update(&self) -> bool {
        let mut is_update = true;
        for key in <Self::Entity as EntityTrait>::PrimaryKey::iter() {
            let col = key.into_column();
            if self.is_not_set(col) {
                is_update = false;
                break;
            }
        }
        is_update
    }

    /// Delete an active model by its primary key
    ///
    /// # Example
    ///
    /// ```
    /// # use sea_orm::{error::*, tests_cfg::*, *};
    /// #
    /// # #[cfg(feature = "mock")]
    /// # pub fn main() -> Result<(), DbErr> {
    /// #
    /// # let db = MockDatabase::new(DbBackend::Postgres)
    /// #     .append_exec_results([
    /// #         MockExecResult {
    /// #             last_insert_id: 0,
    /// #             rows_affected: 1,
    /// #         },
    /// #     ])
    /// #     .into_connection();
    /// #
    /// use sea_orm::{entity::*, query::*, tests_cfg::fruit};
    ///
    /// let orange = fruit::ActiveModel {
    ///     id: Set(3),
    ///     ..Default::default()
    /// };
    ///
    /// let delete_result = orange.delete(&db)?;
    ///
    /// assert_eq!(delete_result.rows_affected, 1);
    ///
    /// assert_eq!(
    ///     db.into_transaction_log(),
    ///     [Transaction::from_sql_and_values(
    ///         DbBackend::Postgres,
    ///         r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
    ///         [3i32.into()]
    ///     )]
    /// );
    /// #
    /// # Ok(())
    /// # }
    /// ```
    fn delete<'a, C>(self, db: &'a C) -> Result<DeleteResult, DbErr>
    where
        Self: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let am = ActiveModelBehavior::before_delete(self, db)?;
        let am_clone = am.clone();
        let delete_res = Self::Entity::delete(am).exec(db)?;
        ActiveModelBehavior::after_delete(am_clone, db)?;
        Ok(delete_res)
    }

    /// Set the corresponding attributes in the ActiveModel from a JSON value
    ///
    /// Note that this method will not alter the primary key values in ActiveModel.
    #[cfg(feature = "with-json")]
    fn set_from_json(&mut self, json: serde_json::Value) -> Result<(), DbErr>
    where
        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
            serde::de::Deserialize<'de> + serde::Serialize,
    {
        use crate::Iterable;

        // Backup primary key values
        let primary_key_values: Vec<(<Self::Entity as EntityTrait>::Column, ActiveValue<Value>)> =
            <<Self::Entity as EntityTrait>::PrimaryKey>::iter()
                .map(|pk| (pk.into_column(), self.take(pk.into_column())))
                .collect();

        // Replace all values in ActiveModel
        *self = Self::from_json(json)?;

        // Restore primary key values
        for (col, active_value) in primary_key_values {
            match active_value {
                ActiveValue::Unchanged(v) | ActiveValue::Set(v) => self.set(col, v),
                NotSet => self.not_set(col),
            }
        }

        Ok(())
    }

    /// Create ActiveModel from a JSON value
    #[cfg(feature = "with-json")]
    fn from_json(json: serde_json::Value) -> Result<Self, DbErr>
    where
        Self: crate::TryIntoModel<<Self::Entity as EntityTrait>::Model>,
        <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
        for<'de> <<Self as ActiveModelTrait>::Entity as EntityTrait>::Model:
            serde::de::Deserialize<'de> + serde::Serialize,
    {
        use crate::{IdenStatic, Iterable};

        let serde_json::Value::Object(mut input) = json else {
            return Err(DbErr::Json(format!(
                "invalid type: expected JSON object for {}",
                <<Self as ActiveModelTrait>::Entity as IdenStatic>::as_str(&Default::default())
            )));
        };

        let dummy_am = Self::default_values();
        let len = <<Self::Entity as EntityTrait>::Column>::iter().len();
        // Mark down which attribute exists in the JSON object
        let mut json_keys = Vec::with_capacity(len);
        let mut merged = serde_json::Map::with_capacity(len);

        for col in <<Self::Entity as EntityTrait>::Column>::iter() {
            let key = col.json_key();
            let has_key = input.contains_key(key);
            json_keys.push((col, has_key));
            match dummy_am.get(col) {
                ActiveValue::Unchanged(value) | ActiveValue::Set(value) => {
                    merged.insert(key.to_owned(), sea_query::sea_value_to_json_value(&value));
                }
                _ => {}
            }
        }

        merged.append(&mut input);
        let _ = input;

        let json_value = serde_json::Value::Object(merged);

        // Convert JSON object into ActiveModel via Model
        let model: <Self::Entity as EntityTrait>::Model =
            serde_json::from_value(json_value).map_err(json_err)?;
        let mut am = model.into_active_model();

        // Transform attribute that exists in JSON object into ActiveValue::Set, otherwise ActiveValue::NotSet
        for (col, json_key_exists) in json_keys {
            match (json_key_exists, am.get(col)) {
                (true, ActiveValue::Set(value) | ActiveValue::Unchanged(value)) => {
                    am.set(col, value);
                }
                _ => {
                    am.not_set(col);
                }
            }
        }

        Ok(am)
    }

    /// Create a Vec of ActiveModels from an Arrow RecordBatch.
    ///
    /// Each row in the RecordBatch becomes one ActiveModel.
    /// Columns are matched by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
    /// Columns present in the RecordBatch are marked as `Set`;
    /// columns absent from the RecordBatch are marked as `NotSet`.
    ///
    /// Supported column types: integers (i8–i64, u8–u64), floats (f32, f64),
    /// `String`/`Text`, `Boolean`, and date/time types (with `with-chrono` or `with-time`).
    /// Null values in nullable columns are handled.
    ///
    /// When both `with-chrono` and `with-time` features are enabled, chrono values
    /// are attempted first. If the model uses time-crate types, the conversion
    /// automatically falls back to the time-crate representation.
    #[cfg(feature = "with-arrow")]
    fn from_arrow(batch: &sea_orm_arrow::arrow::array::RecordBatch) -> Result<Vec<Self>, DbErr> {
        use crate::{IdenStatic, Iterable, with_arrow::arrow_array_to_value};

        let num_rows = batch.num_rows();
        let mut results = Vec::with_capacity(num_rows);

        for row in 0..num_rows {
            let mut am = Self::default();

            for col in <<Self::Entity as EntityTrait>::Column>::iter() {
                let col_name = col.as_str();

                if let Some(arrow_col) = batch.column_by_name(col_name) {
                    let col_def = col.def();
                    let col_type = col_def.get_column_type();
                    let value = arrow_array_to_value(arrow_col.as_ref(), col_type, row)?;

                    // When both chrono and time features are enabled, the primary
                    // conversion produces chrono Values for date/time columns.
                    // If the model's field uses time-crate types, try_set will fail;
                    // retry with the time-crate alternative.
                    #[cfg(all(feature = "with-chrono", feature = "with-time"))]
                    {
                        use crate::with_arrow::{arrow_array_to_value_alt, is_datetime_column};
                        match am.try_set(col, value) {
                            Ok(()) => {}
                            Err(first_err) if is_datetime_column(col_type) => {
                                if let Some(alt_value) =
                                    arrow_array_to_value_alt(arrow_col.as_ref(), col_type, row)?
                                {
                                    am.try_set(col, alt_value)?;
                                } else {
                                    return Err(first_err);
                                }
                            }
                            Err(e) => return Err(e),
                        }
                    }

                    #[cfg(not(all(feature = "with-chrono", feature = "with-time")))]
                    am.try_set(col, value)?;
                } else {
                    am.not_set(col);
                }
            }

            results.push(am);
        }

        Ok(results)
    }

    /// Convert a slice of ActiveModels into an Arrow [`RecordBatch`](arrow::array::RecordBatch).
    ///
    /// The `schema` determines the output columns: each schema field is matched
    /// to an entity column by name (using [`ColumnTrait::as_str`](crate::ColumnTrait::as_str)).
    /// Columns marked `Set` or `Unchanged` contribute their value;
    /// `NotSet` columns become null in the output.
    ///
    /// Typical usage together with [`ArrowSchema`](crate::ArrowSchema):
    /// ```ignore
    /// let schema = MyEntity::arrow_schema();
    /// let batch = MyActiveModel::to_arrow(&models, &schema)?;
    /// ```
    #[cfg(feature = "with-arrow")]
    fn to_arrow(
        models: &[Self],
        schema: &sea_orm_arrow::arrow::datatypes::Schema,
    ) -> Result<sea_orm_arrow::arrow::array::RecordBatch, DbErr> {
        use crate::{Iterable, with_arrow::option_values_to_arrow_array};
        use std::sync::Arc;

        let mut columns: Vec<Arc<dyn sea_orm_arrow::arrow::array::Array>> =
            Vec::with_capacity(schema.fields().len());

        for field in schema.fields() {
            let field_name = field.name();

            // Find the entity column whose name matches this schema field
            let entity_col =
                <<Self::Entity as EntityTrait>::Column>::iter().find(|c| c.as_str() == field_name);

            if let Some(col) = entity_col {
                let values: Vec<Option<Value>> = models
                    .iter()
                    .map(|m| match m.get(col) {
                        ActiveValue::Set(v) | ActiveValue::Unchanged(v) => Some(v),
                        ActiveValue::NotSet => None,
                    })
                    .collect();

                let array = option_values_to_arrow_array(&values, field.data_type())?;
                columns.push(array);
            } else {
                // Field in schema but not in entity → null column
                let array =
                    sea_orm_arrow::arrow::array::new_null_array(field.data_type(), models.len());
                columns.push(array);
            }
        }

        sea_orm_arrow::arrow::array::RecordBatch::try_new(Arc::new(schema.clone()), columns)
            .map_err(|e| DbErr::Type(format!("Failed to create RecordBatch: {e}")))
    }

    /// Return `true` if any attribute of `ActiveModel` is `Set`
    fn is_changed(&self) -> bool {
        <Self::Entity as EntityTrait>::Column::iter()
            .any(|col| matches!(self.get(col), ActiveValue::Set(_)))
    }

    #[doc(hidden)]
    /// Set the key to parent's key value for a belongs to relation.
    fn set_parent_key<R, AM>(&mut self, model: &AM) -> Result<(), DbErr>
    where
        R: EntityTrait,
        AM: ActiveModelTrait<Entity = R>,
        Self::Entity: Related<R>,
    {
        let rel_def = Self::Entity::to();

        if rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation from {} to {} is not belongs_to",
                <Self::Entity as Default>::default().as_str(),
                <R as Default>::default().as_str()
            )));
        }

        let values = get_key_from_active_model(&rel_def.to_col, model)?;

        set_key_on_active_model(&rel_def.from_col, self, values)?;

        Ok(())
    }

    #[doc(hidden)]
    fn set_parent_key_for<R, AM>(
        &mut self,
        model: &AM,
        rel: <Self::Entity as EntityTrait>::Relation,
    ) -> Result<(), DbErr>
    where
        R: EntityTrait,
        AM: ActiveModelTrait<Entity = R>,
    {
        let rel_def = rel.def();

        if rel_def.is_owner {
            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
        }

        let values = get_key_from_active_model(&rel_def.to_col, model)?;

        set_key_on_active_model(&rel_def.from_col, self, values)?;

        Ok(())
    }

    #[doc(hidden)]
    fn set_parent_key_for_def<R, AM>(
        &mut self,
        model: &AM,
        rel_def: &RelationDef,
    ) -> Result<(), DbErr>
    where
        R: EntityTrait,
        AM: ActiveModelTrait<Entity = R>,
    {
        if rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation {rel_def:?} is not belongs_to"
            )));
        }

        let values = get_key_from_active_model(&rel_def.to_col, model)?;

        set_key_on_active_model(&rel_def.from_col, self, values)?;

        Ok(())
    }

    #[doc(hidden)]
    fn set_parent_key_for_self_rev<AM>(
        &mut self,
        model: &AM,
        rel: <Self::Entity as EntityTrait>::Relation,
    ) -> Result<(), DbErr>
    where
        AM: ActiveModelTrait<Entity = Self::Entity>,
    {
        let rel_def = rel.def();

        if !rel_def.is_owner {
            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
        }

        let values = get_key_from_active_model(&rel_def.from_col, model)?;

        set_key_on_active_model(&rel_def.to_col, self, values)?;

        Ok(())
    }

    #[doc(hidden)]
    /// Clear parent association if the relation is optional and return true
    fn clear_parent_key<R>(&mut self) -> Result<bool, DbErr>
    where
        R: EntityTrait,
        Self::Entity: Related<R>,
    {
        let rel_def = Self::Entity::to();

        if rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation from {} to {} is not belongs_to",
                <Self::Entity as Default>::default().as_str(),
                <R as Default>::default().as_str()
            )));
        }

        clear_key_on_active_model(&rel_def.from_col, self)
    }

    #[doc(hidden)]
    fn clear_parent_key_for_self_rev(
        &mut self,
        rel: <Self::Entity as EntityTrait>::Relation,
    ) -> Result<bool, DbErr> {
        let rel_def = rel.def();

        if !rel_def.is_owner {
            return Err(DbErr::Type(format!("Relation {rel:?} is not owner")));
        }

        clear_key_on_active_model(&rel_def.to_col, self)
    }

    #[doc(hidden)]
    /// Get the key value of belongs to relation
    fn get_parent_key<R>(&self) -> Result<ValueTuple, DbErr>
    where
        R: EntityTrait,
        Self::Entity: Related<R>,
    {
        let rel_def = Self::Entity::to();

        if rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation from {} to {} is not belongs_to",
                <Self::Entity as Default>::default().as_str(),
                <R as Default>::default().as_str()
            )));
        }

        get_key_from_active_model(&rel_def.from_col, self)
    }

    #[doc(hidden)]
    /// Get the key value of belongs to relation
    fn get_parent_key_for(
        &self,
        rel: <Self::Entity as EntityTrait>::Relation,
    ) -> Result<ValueTuple, DbErr> {
        let rel_def = rel.def();

        if rel_def.is_owner {
            return Err(DbErr::Type(format!("Relation {rel:?} is not belongs_to")));
        }

        get_key_from_active_model(&rel_def.from_col, self)
    }

    #[doc(hidden)]
    fn find_belongs_to_self(
        &self,
        rel: <Self::Entity as EntityTrait>::Relation,
        db_backend: DbBackend,
    ) -> Result<crate::query::Select<Self::Entity>, DbErr> {
        let rel_def = rel.def();

        if !rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation {rel:?} is not has_one / has_many"
            )));
        }

        let id = get_key_from_active_model(&rel_def.from_col, self)?;

        Ok(Self::Entity::find().filter(
            column_tuple_in_condition(
                &<Self::Entity as Default>::default().table_ref(),
                &rel_def.to_col,
                &[id],
                db_backend,
            )
            .expect(""),
        ))
    }

    #[doc(hidden)]
    fn find_belongs_to_model<AM>(
        rel_def: &RelationDef,
        belongs_to: &AM,
        db_backend: DbBackend,
    ) -> Result<crate::query::Select<Self::Entity>, DbErr>
    where
        AM: ActiveModelTrait,
    {
        if rel_def.is_owner {
            return Err(DbErr::Type(format!(
                "Relation {rel_def:?} is not belongs_to"
            )));
        }

        let id = get_key_from_active_model(&rel_def.to_col, belongs_to)?;
        Ok(<Self::Entity as EntityTrait>::find().filter(
            column_tuple_in_condition(&rel_def.from_tbl, &rel_def.from_col, &[id], db_backend)
                .expect(""),
        ))
    }

    /// Find related Models belonging to self
    fn find_related<R>(&self, _: R) -> crate::query::Select<R>
    where
        R: EntityTrait,
        Self::Entity: Related<R>,
    {
        Self::Entity::find_related().belongs_to_active_model(self)
    }

    /// Like find_related, but infer type from `AM`
    #[doc(hidden)]
    fn find_related_of<AM>(&self, _: &[AM]) -> crate::query::Select<AM::Entity>
    where
        AM: ActiveModelTrait,
        Self::Entity: Related<AM::Entity>,
    {
        self.find_related(AM::Entity::default())
    }

    /// Establish links between self and a related Entity for a many-to-many relation.
    /// New associations will be added, and leftovers can be optionally deleted.
    #[doc(hidden)]
    fn establish_links<J, R, RM, C>(
        &self,
        _: J,
        related_models: &[RM],
        delete_leftover: bool,
        db: &C,
    ) -> Result<(), DbErr>
    where
        R: EntityTrait,
        RM: ActiveModelTrait<Entity = R>,
        J: EntityTrait + Related<R> + Related<Self::Entity>,
        J::Model: IntoActiveModel<J::ActiveModel>,
        J::ActiveModel: ActiveModelBehavior,
        C: ConnectionTrait,
    {
        let left = <J as Related<Self::Entity>>::to();
        let right = <J as Related<R>>::to();

        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
    }

    /// Establish links for self-referencing many-to-many relation
    #[doc(hidden)]
    fn establish_links_self<J, RM, C>(
        &self,
        _: J,
        related_models: &[RM],
        delete_leftover: bool,
        db: &C,
    ) -> Result<(), DbErr>
    where
        RM: ActiveModelTrait<Entity = Self::Entity>,
        J: EntityTrait,
        J::Model: IntoActiveModel<J::ActiveModel>,
        J::ActiveModel: ActiveModelBehavior,
        C: ConnectionTrait,
        Self::Entity: RelatedSelfVia<J>,
    {
        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
        let right = <Self::Entity as RelatedSelfVia<J>>::to();

        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
    }

    /// Establish links for self-referencing many-to-many relation, but left-right reversed
    #[doc(hidden)]
    fn establish_links_self_rev<J, RM, C>(
        &self,
        _: J,
        related_models: &[RM],
        delete_leftover: bool,
        db: &C,
    ) -> Result<(), DbErr>
    where
        RM: ActiveModelTrait<Entity = Self::Entity>,
        J: EntityTrait,
        J::Model: IntoActiveModel<J::ActiveModel>,
        J::ActiveModel: ActiveModelBehavior,
        C: ConnectionTrait,
        Self::Entity: RelatedSelfVia<J>,
    {
        let left = <Self::Entity as RelatedSelfVia<J>>::to();
        let right = <Self::Entity as RelatedSelfVia<J>>::via().rev();

        establish_links::<_, J, _, C>(self, related_models, left, right, delete_leftover, db)
    }

    /// Inverse of establish link, break links between two many-to-many models
    #[doc(hidden)]
    fn delete_links<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
    where
        J: EntityTrait + Related<Self::Entity>,
        C: ConnectionTrait,
    {
        let rel_def = <J as Related<Self::Entity>>::to();
        let id = get_key_from_active_model(&rel_def.to_col, self)?;

        J::delete_many()
            .filter(
                column_tuple_in_condition(
                    &rel_def.from_tbl,
                    &rel_def.from_col,
                    &[id],
                    db.get_database_backend(),
                )
                .expect(""),
            )
            .exec(db)
    }

    /// Like `delete_links` but for self-referencing relations
    #[doc(hidden)]
    fn delete_links_self<J, C>(&self, _: J, db: &C) -> Result<DeleteResult, DbErr>
    where
        J: EntityTrait,
        C: ConnectionTrait,
        Self::Entity: RelatedSelfVia<J>,
    {
        let left = <Self::Entity as RelatedSelfVia<J>>::via().rev();
        let right = <Self::Entity as RelatedSelfVia<J>>::to();

        let id = get_key_from_active_model(&left.to_col, self)?;

        if left.to_col != right.to_col {
            return Err(DbErr::Type("Expect Self Referencing Relation".into()));
        }

        J::delete_many()
            .filter(
                Condition::any()
                    .add(
                        column_tuple_in_condition(
                            &left.from_tbl,
                            &left.from_col,
                            std::slice::from_ref(&id),
                            db.get_database_backend(),
                        )
                        .expect(""),
                    )
                    .add(
                        column_tuple_in_condition(
                            &right.from_tbl,
                            &right.from_col,
                            std::slice::from_ref(&id),
                            db.get_database_backend(),
                        )
                        .expect(""),
                    ),
            )
            .exec(db)
    }
}

/// Lifecycle hooks for an [`ActiveModelTrait`].
///
/// Every entity must have an impl of this trait — even the empty
/// `impl ActiveModelBehavior for ActiveModel {}` you see in the examples is
/// required so that the default `new` / `before_save` / `after_save` /
/// `before_delete` / `after_delete` implementations are wired up. Override
/// the hooks to enforce invariants, populate computed columns, or run side
/// effects around saves and deletes.
///
/// ```ignore
/// use sea_orm::entity::prelude::*;
///
/// impl ActiveModelBehavior for ActiveModel {
///     fn before_save<C>(mut self, _db: &C, insert: bool) -> Result<Self, DbErr>
///     where
///         C: ConnectionTrait,
///     {
///         if insert && self.created_at.is_not_set() {
///             self.created_at = Set(chrono::Utc::now());
///         }
///         self.updated_at = Set(chrono::Utc::now());
///         Ok(self)
///     }
/// }
/// ```
#[allow(unused_variables)]
pub trait ActiveModelBehavior: ActiveModelTrait {
    /// Build a fresh ActiveModel. Defaults to [`ActiveModelTrait::default`]
    /// (every column `NotSet`); override to pre-fill columns:
    ///
    /// ```ignore
    /// fn new() -> Self {
    ///     Self {
    ///         status: Set(Status::New),
    ///         ..ActiveModelTrait::default()
    ///     }
    /// }
    /// ```
    fn new() -> Self {
        <Self as ActiveModelTrait>::default()
    }

    /// Hook invoked before `insert`, `update`, and `save`. `insert` is `true`
    /// for inserts. Return an error to abort the operation.
    fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        Ok(self)
    }

    /// Hook invoked after `insert`, `update`, and `save` succeed. Receives
    /// (and may transform) the resulting `Model`.
    fn after_save<C>(
        model: <Self::Entity as EntityTrait>::Model,
        db: &C,
        insert: bool,
    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr>
    where
        C: ConnectionTrait,
    {
        Ok(model)
    }

    /// Hook invoked before `delete`. Return an error to abort.
    fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        Ok(self)
    }

    /// Hook invoked after `delete` succeeds.
    fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        Ok(self)
    }
}

/// A Trait for any type that can be converted into an `ActiveModel`,
/// can be derived using `DeriveIntoActiveModel`.
///
/// ## Derive Macro Example
///
/// ```rust
/// use sea_orm::DeriveIntoActiveModel;
/// mod fruit {
///     use sea_orm::entity::prelude::*;
///     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
///     #[sea_orm(table_name = "fruit")]
///     pub struct Model {
///         #[sea_orm(primary_key)]
///         pub id: i32,
///         pub name: String,
///         pub cake_id: Option<i32>,
///     }
///     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
///     pub enum Relation {}
///     impl ActiveModelBehavior for ActiveModel {}
/// }
///
/// #[derive(DeriveIntoActiveModel)]
/// #[sea_orm(active_model = "fruit::ActiveModel")]
/// struct NewFruit {
///     name: String,
///     // `id` and `cake_id` are omitted - they become `NotSet`
/// }
/// ```
///
/// ## `set(...)` - always set absent ActiveModel fields
///
/// ```rust
/// # mod fruit {
/// #     use sea_orm::entity::prelude::*;
/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
/// #     #[sea_orm(table_name = "fruit")]
/// #     pub struct Model {
/// #         #[sea_orm(primary_key)]
/// #         pub id: i32,
/// #         pub name: String,
/// #         pub cake_id: Option<i32>,
/// #     }
/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
/// #     pub enum Relation {}
/// #     impl ActiveModelBehavior for ActiveModel {}
/// # }
/// use sea_orm::DeriveIntoActiveModel;
///
/// #[derive(DeriveIntoActiveModel)]
/// #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
/// struct NewFruit {
///     name: String,
///     // `cake_id` is not on the struct, but will always be `Set(None)`
/// }
/// ```
///
/// ## `default = "expr"` - fallback for `Option<T>` struct fields
///
/// ```rust
/// # mod fruit {
/// #     use sea_orm::entity::prelude::*;
/// #     #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
/// #     #[sea_orm(table_name = "fruit")]
/// #     pub struct Model {
/// #         #[sea_orm(primary_key)]
/// #         pub id: i32,
/// #         pub name: String,
/// #         pub cake_id: Option<i32>,
/// #     }
/// #     #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
/// #     pub enum Relation {}
/// #     impl ActiveModelBehavior for ActiveModel {}
/// # }
/// use sea_orm::DeriveIntoActiveModel;
///
/// #[derive(DeriveIntoActiveModel)]
/// #[sea_orm(active_model = "fruit::ActiveModel")]
/// struct UpdateFruit {
///     /// `Some("Apple")` -> `Set("Apple")`, `None` ->`Set("Unnamed")`
///     #[sea_orm(default = "String::from(\"Unnamed\")")]
///     name: Option<String>,
/// }
/// ```
pub trait IntoActiveModel<A>
where
    A: ActiveModelTrait,
{
    /// Method to call to perform the conversion
    fn into_active_model(self) -> A;
}

impl<A> IntoActiveModel<A> for A
where
    A: ActiveModelTrait,
{
    fn into_active_model(self) -> A {
        self
    }
}

fn establish_links<EM, J, RM, C>(
    model: &EM,
    related_models: &[RM],
    left: RelationDef,
    right: RelationDef,
    delete_leftover: bool,
    db: &C,
) -> Result<(), DbErr>
where
    EM: ActiveModelTrait,
    RM: ActiveModelTrait,
    J: EntityTrait,
    J::Model: IntoActiveModel<J::ActiveModel>,
    J::ActiveModel: ActiveModelBehavior,
    C: ConnectionTrait,
{
    let mut require_leftover = true;

    if related_models.is_empty() {
        // if there are no related models, then there is no risk of insert conflict
        require_leftover = false;
    }

    let primary_key = J::primary_key_identity();
    if require_leftover
        && primary_key.fully_contains(&left.from_col)
        && primary_key.fully_contains(&right.from_col)
    {
        // if the primary key is a composite key of the two relations
        // we can use on conflict no action safely
        require_leftover = false;
    }

    let mut leftover = Vec::new();
    if delete_leftover || require_leftover {
        for item in <J::ActiveModel as ActiveModelTrait>::find_belongs_to_model(
            &left,
            model,
            db.get_database_backend(),
        )?
        .all(db)?
        {
            let item = item.into_active_model();
            let key = get_key_from_active_model(&right.from_col, &item)?;
            leftover.push((item, key));
        }
    }
    let leftover = leftover; // un-mut

    let mut via_models = Vec::new();
    let mut all_keys = std::collections::HashSet::new();

    for related_model in related_models {
        let mut via: J::ActiveModel = ActiveModelBehavior::new();
        via.set_parent_key_for_def(model, &left)?;
        via.set_parent_key_for_def(related_model, &right)?;
        let via_key = get_key_from_active_model(&right.from_col, &via)?;
        if !leftover.iter().any(|t| t.1 == via_key) {
            // if not already exist, save for insert
            via_models.push(via);
        }
        if delete_leftover {
            all_keys.insert(via_key);
        }
    }

    if delete_leftover {
        let mut to_delete = Vec::new();
        let mut to_delete_am = Vec::new();
        for (leftover, key) in leftover {
            if !all_keys.contains(&key) {
                to_delete.push(
                    leftover
                        .get_primary_key_value()
                        .expect("item is a full model"),
                );
                to_delete_am.push(leftover);
            }
        }
        if !to_delete.is_empty() {
            // run before_delete hooks
            for am in to_delete_am.clone() {
                am.before_delete(db)?;
            }
            if db.support_returning() {
                let deleted = J::delete_many()
                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
                    .exec_with_returning(db)?;
                // run after_delete hooks with the returned value if possible
                for am in deleted {
                    let am = am.into_active_model();
                    let _ = am.after_delete(db)?;
                }
            } else {
                J::delete_many()
                    .filter_by_value_tuples(&to_delete, db.get_database_backend())
                    .exec(db)?;
                // fall back to the saved values if returning is not supported
                for am in to_delete_am {
                    let _ = am.after_delete(db)?;
                }
            }
        }
    }

    if !via_models.is_empty() {
        // run the before_save hooks
        let mut via_models_res = Vec::with_capacity(via_models.len());
        for am in via_models {
            let am = am.before_save(db, true)?;
            via_models_res.push(am);
        }

        // insert new junctions
        if db.support_returning() {
            // use the returned value if it is supported
            let res = J::insert_many(via_models_res)
                .on_conflict_do_nothing()
                .exec_with_returning_many(db)?;
            // run after_save hooks
            if let TryInsertResult::Inserted(inserted) = res {
                for model in inserted {
                    let _ = J::ActiveModel::after_save(model, db, true)?;
                }
            }
        } else {
            // fall back to individual inserts if returning is not supported
            for model in via_models_res {
                let res = J::insert(model)
                    .on_conflict_do_nothing()
                    .exec_with_returning(db)?;
                if let TryInsertResult::Inserted(model) = res {
                    let _ = J::ActiveModel::after_save(model, db, true)?;
                }
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use crate::{DbErr, entity::*, tests_cfg::*};
    use pretty_assertions::assert_eq;

    #[cfg(feature = "with-json")]
    use serde_json::json;

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_1() {
        mod my_fruit {
            pub use super::fruit::*;
            use crate as sea_orm;
            use crate::entity::prelude::*;

            #[derive(DeriveIntoActiveModel)]
            pub struct NewFruit {
                // id is omitted
                pub name: String,
                // it is required as opposed to optional in Model
                pub cake_id: i32,
            }
        }

        assert_eq!(
            my_fruit::NewFruit {
                name: "Apple".to_owned(),
                cake_id: 1,
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(1)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_2() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct RequiredFruitName {
            name: String,
        }

        assert_eq!(
            RequiredFruitName {
                name: "Apple Pie".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple Pie".to_owned()),
                cake_id: NotSet,
            }
        );

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct OptionalFruitName {
            name: Option<String>,
        }

        assert_eq!(
            OptionalFruitName {
                name: Some("Apple Pie".to_owned()),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple Pie".to_owned()),
                cake_id: NotSet,
            }
        );

        assert_eq!(
            OptionalFruitName { name: None }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: NotSet,
            }
        );

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
        struct RequiredAndNotNullFruitCake {
            cake_id: i32,
        }

        assert_eq!(
            RequiredAndNotNullFruitCake { cake_id: 1 }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: Set(Some(1)),
            }
        );

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
        struct OptionalAndNotNullFruitCake {
            cake_id: Option<i32>,
        }

        assert_eq!(
            OptionalAndNotNullFruitCake { cake_id: Some(1) }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: Set(Some(1)),
            }
        );

        assert_eq!(
            OptionalAndNotNullFruitCake { cake_id: None }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: NotSet,
            }
        );

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "<fruit::Entity as EntityTrait>::ActiveModel")]
        struct OptionalAndNullableFruitCake {
            cake_id: Option<Option<i32>>,
        }

        assert_eq!(
            OptionalAndNullableFruitCake {
                cake_id: Some(Some(1)),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: Set(Some(1)),
            }
        );

        assert_eq!(
            OptionalAndNullableFruitCake {
                cake_id: Some(None),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: Set(None),
            }
        );

        assert_eq!(
            OptionalAndNullableFruitCake { cake_id: None }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: NotSet,
                cake_id: NotSet,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_set_single() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "None"))]
        struct NewFruit {
            name: String,
        }

        assert_eq!(
            NewFruit {
                name: "Apple".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(None),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_set_multiple() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(
            active_model = "fruit::ActiveModel",
            set(name = "String::from(\"cherry\")", cake_id = "None")
        )]
        struct IdOnlyFruit {
            id: i32,
        }
        assert_eq!(
            IdOnlyFruit { id: 1 }.into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("cherry".to_owned()),
                cake_id: Set(None),
            }
        );

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(
            active_model = "fruit::ActiveModel",
            set(name = "String::from(\"cherry\")"),
            set(cake_id = "None")
        )]
        struct IdOnlyFruit2 {
            id: i32,
        }
        assert_eq!(
            IdOnlyFruit2 { id: 1 }.into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("cherry".to_owned()),
                cake_id: Set(None),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_set_separate_attrs() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(
            active_model = "fruit::ActiveModel",
            set(name = "String::from(\"cherry\")")
        )]
        #[sea_orm(set(cake_id = "None"))]
        struct IdOnlyFruit {
            id: i32,
        }

        assert_eq!(
            IdOnlyFruit { id: 1 }.into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("cherry".to_owned()),
                cake_id: Set(None),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_ignore() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            name: String,
            cake_id: i32,
            #[sea_orm(ignore)]
            _extra: String,
        }

        assert_eq!(
            NewFruit {
                name: "Apple".to_owned(),
                cake_id: 1,
                _extra: "ignored".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(1)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_skip() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            name: String,
            #[sea_orm(skip)]
            _extra: String,
        }

        assert_eq!(
            NewFruit {
                name: "Apple".to_owned(),
                _extra: "skipped".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: NotSet,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_set_and_ignore() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(42)"))]
        struct NewFruit {
            name: String,
            #[sea_orm(ignore)]
            _extra: String,
        }

        assert_eq!(
            NewFruit {
                name: "Apple".to_owned(),
                _extra: "ignored".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(42)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_foreign_ignore() {
        use serde::{Deserialize, Serialize};

        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel, Serialize, Deserialize)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            #[sea_orm(ignore)]
            id: i32,
            name: String,
            #[serde(skip)]
            cake_id: Option<i32>,
        }

        assert_eq!(
            NewFruit {
                id: 1.to_owned(),
                name: "Apple".to_owned(),
                cake_id: Some(42)
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(42)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_exhaustive() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
        struct FullFruit {
            id: i32,
            name: String,
        }

        assert_eq!(
            FullFruit {
                id: 1,
                name: "Apple".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("Apple".to_owned()),
                cake_id: Set(None),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_multiple_sets() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        const DEFULT_CAKE_ID: i32 = 1;
        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(
            active_model = "fruit::ActiveModel",
            exhaustive,
            set(cake_id = "Some(DEFULT_CAKE_ID)")
        )]
        struct FullFruit {
            id: i32,
            name: String,
        }

        assert_eq!(
            FullFruit {
                id: 1,
                name: "Apple".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(1)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_field_empty_default() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            #[sea_orm(default)]
            name: Option<String>,
        }

        // Some(v) -> Set(v)
        assert_eq!(
            NewFruit {
                name: Some("Apple".to_owned()),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: NotSet,
            }
        );

        // None -> Set(fallback)
        assert_eq!(
            NewFruit { name: None }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("".to_owned()),
                cake_id: NotSet,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_field_custom_option() {
        use crate as sea_orm;
        use crate::entity::prelude::*;
        mod foreign_crate {
            #[derive(Debug, Clone, PartialEq, Eq)]
            pub enum CustomOption<T> {
                None,
                Some(T),
            }

            impl From<CustomOption<String>> for Option<String> {
                fn from(option: CustomOption<String>) -> Self {
                    match option {
                        CustomOption::None => Option::None,
                        CustomOption::Some(value) => value.into(),
                    }
                }
            }
        }
        use foreign_crate::CustomOption;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            #[sea_orm(default)]
            name: CustomOption<String>,
        }

        // Some(v) -> Set(v)
        assert_eq!(
            NewFruit {
                name: CustomOption::Some("Apple".to_owned()),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: NotSet,
            }
        );

        // None -> Set(fallback)
        assert_eq!(
            NewFruit {
                name: CustomOption::None
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("".to_owned()),
                cake_id: NotSet,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_field_default_some() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel")]
        struct NewFruit {
            #[sea_orm(default = "String::from(\"Unnamed\")")]
            name: Option<String>,
        }

        // Some(v) -> Set(v)
        assert_eq!(
            NewFruit {
                name: Some("Apple".to_owned()),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: NotSet,
            }
        );

        // None -> Set(fallback)
        assert_eq!(
            NewFruit { name: None }.into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Unnamed".to_owned()),
                cake_id: NotSet,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_field_default_with_set() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel", set(cake_id = "Some(99)"))]
        struct NewFruit {
            #[sea_orm(default = "String::from(\"Unnamed\")")]
            name: Option<String>,
            #[sea_orm(ignore)]
            _extra: String,
        }

        assert_eq!(
            NewFruit {
                name: Some("Apple".to_owned()),
                _extra: "ignored".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(99)),
            }
        );

        assert_eq!(
            NewFruit {
                name: None,
                _extra: "ignored".to_owned(),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: NotSet,
                name: Set("Unnamed".to_owned()),
                cake_id: Set(Some(99)),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_into_active_model_field_default_exhaustive() {
        use crate as sea_orm;
        use crate::entity::prelude::*;

        #[derive(DeriveIntoActiveModel)]
        #[sea_orm(active_model = "fruit::ActiveModel", exhaustive, set(cake_id = "None"))]
        struct NewFruit {
            id: i32,
            #[sea_orm(default = "String::from(\"Unnamed\")")]
            name: Option<String>,
        }

        assert_eq!(
            NewFruit {
                id: 1,
                name: Some("Apple".to_owned()),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("Apple".to_owned()),
                cake_id: Set(None),
            }
        );

        assert_eq!(
            NewFruit { id: 2, name: None }.into_active_model(),
            fruit::ActiveModel {
                id: Set(2),
                name: Set("Unnamed".to_owned()),
                cake_id: Set(None),
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_try_into_model_1() {
        mod my_fruit {
            use crate as sea_orm;
            use crate::entity::prelude::*;

            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
            #[sea_orm(table_name = "fruit")]
            pub struct Model {
                #[sea_orm(primary_key)]
                pub id: i32,
                pub name: String,
                pub cake_id: Option<i32>,
            }

            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
            pub enum Relation {}

            impl ActiveModelBehavior for ActiveModel {}
        }
        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(1),
                name: Set("Pineapple".to_owned()),
                cake_id: Set(None),
            }
            .try_into_model()
            .unwrap(),
            my_fruit::Model {
                id: 1,
                name: "Pineapple".to_owned(),
                cake_id: None,
            }
        );

        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(2),
                name: Set("Apple".to_owned()),
                cake_id: Set(Some(1)),
            }
            .try_into_model()
            .unwrap(),
            my_fruit::Model {
                id: 2,
                name: "Apple".to_owned(),
                cake_id: Some(1),
            }
        );

        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(1),
                name: NotSet,
                cake_id: Set(None),
            }
            .try_into_model(),
            Err(DbErr::AttrNotSet(String::from("name")))
        );

        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(1),
                name: Set("Pineapple".to_owned()),
                cake_id: NotSet,
            }
            .try_into_model(),
            Err(DbErr::AttrNotSet(String::from("cake_id")))
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_try_into_model_2() {
        mod my_fruit {
            use crate as sea_orm;
            use crate::entity::prelude::*;

            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
            #[sea_orm(table_name = "fruit")]
            pub struct Model {
                #[sea_orm(primary_key)]
                pub id: i32,
                pub name: String,
                #[sea_orm(ignore)]
                pub cake_id: Option<i32>,
            }

            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
            pub enum Relation {}

            impl ActiveModelBehavior for ActiveModel {}
        }
        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(1),
                name: Set("Pineapple".to_owned()),
            }
            .try_into_model()
            .unwrap(),
            my_fruit::Model {
                id: 1,
                name: "Pineapple".to_owned(),
                cake_id: None,
            }
        );
    }

    #[test]
    #[cfg(feature = "macros")]
    fn test_derive_try_into_model_3() {
        mod my_fruit {
            use crate as sea_orm;
            use crate::entity::prelude::*;

            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
            #[sea_orm(table_name = "fruit")]
            pub struct Model {
                #[sea_orm(primary_key)]
                pub id: i32,
                #[sea_orm(ignore)]
                pub name: String,
                pub cake_id: Option<i32>,
            }

            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
            pub enum Relation {}

            impl ActiveModelBehavior for ActiveModel {}
        }
        assert_eq!(
            my_fruit::ActiveModel {
                id: Set(1),
                cake_id: Set(Some(1)),
            }
            .try_into_model()
            .unwrap(),
            my_fruit::Model {
                id: 1,
                name: "".to_owned(),
                cake_id: Some(1),
            }
        );
    }

    #[test]
    #[cfg(feature = "with-json")]
    fn test_active_model_set_from_json_1() {
        assert_eq!(
            cake::ActiveModel::from_json(json!({
                "id": 1,
                "name": "Apple Pie",
            }))
            .unwrap(),
            cake::ActiveModel {
                id: Set(1),
                name: Set("Apple Pie".to_owned()),
            }
        );

        assert_eq!(
            cake::ActiveModel::from_json(json!({
                "id": 1,
            }))
            .unwrap(),
            cake::ActiveModel {
                id: Set(1),
                name: NotSet,
            }
        );

        assert_eq!(
            cake::ActiveModel::from_json(json!({
                "name": "Apple Pie",
            }))
            .unwrap(),
            cake::ActiveModel {
                id: NotSet,
                name: Set("Apple Pie".to_owned()),
            }
        );

        let mut cake: cake::ActiveModel = Default::default();
        cake.set_from_json(json!({
            "name": "Apple Pie",
        }))
        .unwrap();
        assert_eq!(
            cake,
            cake::ActiveModel {
                id: NotSet,
                name: Set("Apple Pie".to_owned()),
            }
        );
    }

    #[test]
    #[cfg(feature = "with-json")]
    fn test_active_model_set_from_json_2() -> Result<(), DbErr> {
        let mut fruit: fruit::ActiveModel = Default::default();

        fruit.set_from_json(json!({
            "name": "Apple",
        }))?;
        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: ActiveValue::NotSet,
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::NotSet,
            }
        );

        assert_eq!(
            fruit::ActiveModel::from_json(json!({
                "name": "Apple",
            }))?,
            fruit::ActiveModel {
                id: ActiveValue::NotSet,
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::NotSet,
            }
        );

        fruit.set_from_json(json!({
            "name": "Apple",
            "cake_id": null,
        }))?;
        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: ActiveValue::NotSet,
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::Set(None),
            }
        );

        fruit.set_from_json(json!({
            "id": null,
            "name": "Apple",
            "cake_id": 1,
        }))?;
        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: ActiveValue::NotSet,
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::Set(Some(1)),
            }
        );

        fruit.set_from_json(json!({
            "id": 2,
            "name": "Apple",
            "cake_id": 1,
        }))?;
        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: ActiveValue::NotSet,
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::Set(Some(1)),
            }
        );

        let mut fruit = fruit::ActiveModel {
            id: ActiveValue::Set(1),
            name: ActiveValue::NotSet,
            cake_id: ActiveValue::NotSet,
        };
        fruit.set_from_json(json!({
            "id": 8,
            "name": "Apple",
            "cake_id": 1,
        }))?;
        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: ActiveValue::Set(1),
                name: ActiveValue::Set("Apple".to_owned()),
                cake_id: ActiveValue::Set(Some(1)),
            }
        );

        Ok(())
    }

    #[test]
    #[cfg(feature = "with-json")]
    fn test_active_model_set_from_json_3() -> Result<(), DbErr> {
        use crate::*;

        let db = MockDatabase::new(DbBackend::Postgres)
            .append_exec_results([
                MockExecResult {
                    last_insert_id: 1,
                    rows_affected: 1,
                },
                MockExecResult {
                    last_insert_id: 1,
                    rows_affected: 1,
                },
            ])
            .append_query_results([
                [fruit::Model {
                    id: 1,
                    name: "Apple".to_owned(),
                    cake_id: None,
                }],
                [fruit::Model {
                    id: 2,
                    name: "Orange".to_owned(),
                    cake_id: Some(1),
                }],
            ])
            .into_connection();

        let mut fruit: fruit::ActiveModel = Default::default();
        fruit.set_from_json(json!({
            "name": "Apple",
        }))?;
        fruit.save(&db)?;

        let mut fruit = fruit::ActiveModel {
            id: Set(2),
            ..Default::default()
        };
        fruit.set_from_json(json!({
            "id": 9,
            "name": "Orange",
            "cake_id": 1,
        }))?;
        fruit.save(&db)?;

        assert_eq!(
            db.into_transaction_log(),
            [
                Transaction::from_sql_and_values(
                    DbBackend::Postgres,
                    r#"INSERT INTO "fruit" ("name") VALUES ($1) RETURNING "id", "name", "cake_id""#,
                    ["Apple".into()],
                ),
                Transaction::from_sql_and_values(
                    DbBackend::Postgres,
                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
                    ["Orange".into(), 1i32.into(), 2i32.into()],
                ),
            ]
        );

        Ok(())
    }

    #[test]
    fn test_active_model_is_changed() {
        let mut fruit: fruit::ActiveModel = Default::default();
        assert!(!fruit.is_changed());

        fruit.set(fruit::Column::Name, "apple".into());
        assert!(fruit.is_changed());

        let mut fruit = fruit::Model {
            id: 1,
            name: "".into(),
            cake_id: None,
        };
        fruit.set("name".parse().unwrap(), "orange".into());
        assert_eq!(fruit.name, "orange");
    }

    #[test]
    fn test_reset_1() {
        assert_eq!(
            fruit::Model {
                id: 1,
                name: "Apple".into(),
                cake_id: None,
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: Unchanged(1),
                name: Unchanged("Apple".into()),
                cake_id: Unchanged(None)
            },
        );

        assert_eq!(
            fruit::Model {
                id: 1,
                name: "Apple".into(),
                cake_id: None,
            }
            .into_active_model()
            .reset_all(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("Apple".into()),
                cake_id: Set(None)
            },
        );

        assert_eq!(
            fruit::Model {
                id: 1,
                name: "Apple".into(),
                cake_id: Some(2),
            }
            .into_active_model(),
            fruit::ActiveModel {
                id: Unchanged(1),
                name: Unchanged("Apple".into()),
                cake_id: Unchanged(Some(2)),
            },
        );

        assert_eq!(
            fruit::Model {
                id: 1,
                name: "Apple".into(),
                cake_id: Some(2),
            }
            .into_active_model()
            .reset_all(),
            fruit::ActiveModel {
                id: Set(1),
                name: Set("Apple".into()),
                cake_id: Set(Some(2)),
            },
        );
    }

    #[test]
    fn test_reset_2() -> Result<(), DbErr> {
        use crate::*;

        let db = MockDatabase::new(DbBackend::Postgres)
            .append_exec_results(vec![
                MockExecResult {
                    last_insert_id: 1,
                    rows_affected: 1,
                },
                MockExecResult {
                    last_insert_id: 1,
                    rows_affected: 1,
                },
            ])
            .append_query_results(vec![
                vec![fruit::Model {
                    id: 1,
                    name: "Apple".to_owned(),
                    cake_id: None,
                }],
                vec![fruit::Model {
                    id: 1,
                    name: "Apple".to_owned(),
                    cake_id: None,
                }],
            ])
            .into_connection();

        fruit::Model {
            id: 1,
            name: "Apple".into(),
            cake_id: None,
        }
        .into_active_model()
        .update(&db)?;

        fruit::Model {
            id: 1,
            name: "Apple".into(),
            cake_id: None,
        }
        .into_active_model()
        .reset_all()
        .update(&db)?;

        assert_eq!(
            db.into_transaction_log(),
            vec![
                Transaction::from_sql_and_values(
                    DbBackend::Postgres,
                    r#"SELECT "fruit"."id", "fruit"."name", "fruit"."cake_id" FROM "fruit" WHERE "fruit"."id" = $1 LIMIT $2"#,
                    vec![1i32.into(), 1u64.into()],
                ),
                Transaction::from_sql_and_values(
                    DbBackend::Postgres,
                    r#"UPDATE "fruit" SET "name" = $1, "cake_id" = $2 WHERE "fruit"."id" = $3 RETURNING "id", "name", "cake_id""#,
                    vec!["Apple".into(), Option::<i32>::None.into(), 1i32.into()],
                ),
            ]
        );

        Ok(())
    }

    #[test]
    fn test_active_model_default_values() {
        assert_eq!(
            fruit::ActiveModel::default_values(),
            fruit::ActiveModel {
                id: Set(0),
                name: Set("".into()),
                cake_id: Set(None),
            },
        );

        assert_eq!(
            lunch_set::ActiveModel::default_values(),
            lunch_set::ActiveModel {
                id: Set(0),
                name: Set("".into()),
                tea: NotSet,
            },
        );
    }

    #[test]
    fn test_active_model_set_parent_key() {
        let mut fruit = fruit::Model {
            id: 2,
            name: "F".into(),
            cake_id: None,
        }
        .into_active_model();

        let cake = cake::Model {
            id: 4,
            name: "C".into(),
        }
        .into_active_model();

        fruit.set_parent_key(&cake).unwrap();

        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: Unchanged(2),
                name: Unchanged("F".into()),
                cake_id: Set(Some(4)),
            }
        );

        assert!(fruit.clear_parent_key::<cake::Entity>().unwrap());

        assert_eq!(
            fruit,
            fruit::ActiveModel {
                id: Unchanged(2),
                name: Unchanged("F".into()),
                cake_id: Set(None),
            }
        );

        let mut cake_filling = cake_filling::ActiveModel::new();

        cake_filling.set_parent_key(&cake).unwrap();

        assert_eq!(
            cake_filling,
            cake_filling::ActiveModel {
                cake_id: Set(4),
                filling_id: NotSet,
            }
        );
    }
}
