sea-orm/CHANGELOG.md
2023-06-13 21:07:20 +08:00

63 KiB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

0.12.0 - Pending

  • 2023-05-19: 0.12.0-rc.2

New Features

  • Supports for partial select of Option<T> model field. A None value will be filled when the select result does not contain the Option<T> field without throwing an error. https://github.com/SeaQL/sea-orm/pull/1513
customer::ActiveModel {
    name: Set("Alice".to_owned()),
    notes: Set(Some("Want to communicate with Bob".to_owned())),
    ..Default::default()
}
.save(db)
.await?;

// The `notes` field was intentionally leaved out
let customer = Customer::find()
    .select_only()
    .column(customer::Column::Id)
    .column(customer::Column::Name)
    .one(db)
    .await
    .unwrap();

// The select result does not contain `notes` field.
// Since it's of type `Option<String>`, it'll be `None` and no error will be thrown.
assert_eq!(customers.notes, None);
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
    fn migrations() -> Vec<Box<dyn MigrationTrait>> {
        vec![
            Box::new(m20220118_000001_create_cake_table::Migration),
            Box::new(m20220118_000002_create_fruit_table::Migration),
        ]
    }

    // Override the name of migration table
    fn migration_table_name() -> sea_orm::DynIden {
        Alias::new("override_migration_table_name").into_iden()
    }
}
use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cake")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    #[sea_orm(column_name = "name", enum_name = "Name")]
    pub name: String,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    // By default, it's
    // `JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'`
    #[sea_orm(
        has_many = "super::fruit::Entity",
        on_condition = r#"super::fruit::Column::Name.like("%tropical%")"#
    )]
    TropicalFruit,
    // Or specify `condition_type = "any"` to override it,
    // `JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` OR `fruit`.`name` LIKE '%tropical%'`
    #[sea_orm(
        has_many = "super::fruit::Entity",
        on_condition = r#"super::fruit::Column::Name.like("%tropical%")"#
        condition_type = "any",
    )]
    OrTropicalFruit,
}

impl ActiveModelBehavior for ActiveModel {}

You can also override it in custom join.

assert_eq!(
    cake::Entity::find()
        .column_as(
            Expr::col((Alias::new("cake_filling_alias"), cake_filling::Column::CakeId)),
            "cake_filling_cake_id"
        )
        .join(JoinType::LeftJoin, cake::Relation::OrTropicalFruit.def())
        .join_as_rev(
            JoinType::LeftJoin,
            cake_filling::Relation::Cake
                .def()
                // chained AND / OR join on condition
                .condition_type(ConditionType::Any)
                .on_condition(|left, _right| {
                    Expr::col((left, cake_filling::Column::CakeId))
                        .gt(10)
                        .into_condition()
                }),
            Alias::new("cake_filling_alias")
        )
        .build(DbBackend::MySql)
        .to_string(),
    [
        "SELECT `cake`.`id`, `cake`.`name`, `cake_filling_alias`.`cake_id` AS `cake_filling_cake_id` FROM `cake`",
        "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` OR `fruit`.`name` LIKE '%tropical%'",
        "LEFT JOIN `cake_filling` AS `cake_filling_alias` ON `cake_filling_alias`.`cake_id` = `cake`.`id` OR `cake_filling_alias`.`cake_id` > 10",
    ]
    .join(" ")
);
use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "primary_key_of_12")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_1: String,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_2: i8,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_3: u8,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_4: i16,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_5: u16,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_6: i32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_7: u32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_8: i64,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_9: u64,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_10: f32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_11: f64,
    #[sea_orm(primary_key, auto_increment = false)]
    pub id_12: bool,
    pub owner: String,
    pub name: String,
    pub description: String,
}

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

impl ActiveModelBehavior for ActiveModel {}
#[derive(DerivePartialModel, FromQueryResult)]
#[sea_orm(entity = "Cake")]
struct PartialCake {
    name: String,
    #[sea_orm(
        from_expr = r#"SimpleExpr::FunctionCall(Func::upper(Expr::col((Cake, cake::Column::Name))))"#
    )]
    name_upper: String,
}

assert_eq!(
    cake::Entity::find()
        .into_partial_model::<PartialCake>()
        .into_statement(DbBackend::Sqlite)
        .to_string(),
    r#"SELECT "cake"."name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
);
/// ... Entity File ...

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)]
pub enum RelatedEntity {
    #[sea_orm(entity = "super::address::Entity")]
    Address,
    #[sea_orm(entity = "super::payment::Entity")]
    Payment,
    #[sea_orm(entity = "super::rental::Entity")]
    Rental,
    #[sea_orm(entity = "Entity", def = "Relation::SelfRef.def()")]
    SelfRef,
    #[sea_orm(entity = "super::store::Entity")]
    Store,
    #[sea_orm(entity = "Entity", def = "Relation::SelfRef.def().rev()")]
    SelfRefRev,
}
  • Add DeriveEntityRelated macro https://github.com/SeaQL/sea-orm/pull/1599

    The DeriveRelatedEntity derive macro will implement seaography::RelationBuilder for RelatedEntity enumeration when the seaography feature is enabled

  • Add expr, exprs and expr_as methods to QuerySelect trait

use sea_orm::sea_query::Expr;
use sea_orm::{entity::*, tests_cfg::cake, DbBackend, QuerySelect, QueryTrait};

assert_eq!(
    cake::Entity::find()
        .select_only()
        .expr(Expr::col((cake::Entity, cake::Column::Id)))
        .build(DbBackend::MySql)
        .to_string(),
    "SELECT `cake`.`id` FROM `cake`"
);

assert_eq!(
    cake::Entity::find()
        .select_only()
        .exprs([
            Expr::col((cake::Entity, cake::Column::Id)),
            Expr::col((cake::Entity, cake::Column::Name)),
        ])
        .build(DbBackend::MySql)
        .to_string(),
    "SELECT `cake`.`id`, `cake`.`name` FROM `cake`"
);

assert_eq!(
    cake::Entity::find()
        .expr_as(
            Func::upper(Expr::col((cake::Entity, cake::Column::Name))),
            "name_upper"
        )
        .build(DbBackend::MySql)
        .to_string(),
    "SELECT `cake`.`id`, `cake`.`name`, UPPER(`cake`.`name`) AS `name_upper` FROM `cake`"
);

Enhancements

let migrations = Migrator::get_pending_migrations(db).await?;
assert_eq!(migrations.len(), 5);

let migration = migrations.get(0).unwrap();
assert_eq!(migration.name(), "m20220118_000002_create_fruit_table");
assert_eq!(migration.status(), MigrationStatus::Pending);
  • The postgres-array feature will be enabled when sqlx-postgres backend is selected https://github.com/SeaQL/sea-orm/pull/1565
  • Replace String parameters in API with Into<String> https://github.com/SeaQL/sea-orm/pull/1439
    • Implements IntoMockRow for any BTreeMap that is indexed by string impl IntoMockRow for BTreeMap<T, Value> where T: Into<String>
    • Converts any string value into ConnectOptions - impl From<T> for ConnectOptions where T: Into<String>
    • Changed the parameter of method ConnectOptions::new(T) where T: Into<String> to takes any string SQL
    • Changed the parameter of method Statement::from_string(DbBackend, T) where T: Into<String> to takes any string SQL
    • Changed the parameter of method Statement::from_sql_and_values(DbBackend, T, I) where I: IntoIterator<Item = Value>, T: Into<String> to takes any string SQL
    • Changed the parameter of method Transaction::from_sql_and_values(DbBackend, T, I) where I: IntoIterator<Item = Value>, T: Into<String> to takes any string SQL
    • Changed the parameter of method ConnectOptions::set_schema_search_path(T) where T: Into<String> to takes any string
    • Changed the parameter of method ColumnTrait::like(), ColumnTrait::not_like(), ColumnTrait::starts_with(), ColumnTrait::ends_with() and ColumnTrait::contains() to takes any string
  • Re-export sea_query::{DynIden, RcOrArc, SeaRc} in sea_orm::entity::prelude module https://github.com/SeaQL/sea-orm/pull/1661
  • Added DatabaseConnection::ping https://github.com/SeaQL/sea-orm/pull/1627
|db: DatabaseConnection| {
    assert!(db.ping().await.is_ok());
    db.clone().close().await;
    assert!(matches!(db.ping().await, Err(DbErr::ConnectionAcquire)));
}

Upgrades

Bug Fixes

For example,

#[derive(Clone, Debug, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "String(None)")]
pub enum StringValue {
    #[sea_orm(string_value = "")]
    Member1,
    #[sea_orm(string_value = "$")]
    Member2,
    #[sea_orm(string_value = "$$")]
    Member3,
    #[sea_orm(string_value = "AB")]
    Member4,
    #[sea_orm(string_value = "A_B")]
    Member5,
    #[sea_orm(string_value = "A$B")]
    Member6,
    #[sea_orm(string_value = "0 123")]
    Member7,
}

will now produce the following Variant Enum:

pub enum StringValueVariant {
    __Empty,
    _0x24,
    _0x240x24,
    Ab,
    A0x5Fb,
    A0x24B,
    _0x300x20123,
}
  • [sea-orm-cli] The implementation of Related<R> with via and to methods will not be generated if there exists multiple paths via an intermediate table. Like in the schema defined below - Path 1. users <-> users_votes <-> bills, Path 2. users <-> users_saved_bills <-> bills https://github.com/SeaQL/sea-orm/pull/1435
CREATE TABLE users
(
  id uuid  PRIMARY KEY  DEFAULT uuid_generate_v1mc(),
  email TEXT UNIQUE NOT NULL,
  ...
);
CREATE TABLE bills
(
  id uuid  PRIMARY KEY  DEFAULT uuid_generate_v1mc(),
  ...
);
CREATE TABLE users_votes
(
  user_id uuid REFERENCES users (id) ON UPDATE CASCADE ON DELETE CASCADE,
  bill_id uuid REFERENCES bills (id) ON UPDATE CASCADE ON DELETE CASCADE,
  vote boolean NOT NULL,
  CONSTRAINT users_bills_pkey PRIMARY KEY (user_id, bill_id)
);
CREATE TABLE users_saved_bills
(
  user_id uuid REFERENCES users (id) ON UPDATE CASCADE ON DELETE CASCADE,
  bill_id uuid REFERENCES bills (id) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT users_saved_bills_pkey PRIMARY KEY (user_id, bill_id)
);
impl ColumnTrait for Column {
    type EntityName = Entity;
    fn def(&self) -> ColumnDef {
        match self {
...
            // `db_type()` returns `ColumnDef`; now it implements `ColumnTypeTrait`
            Self::Thing => AnActiveEnumThing::db_type().def(),
...
        }
    }
}

Breaking changes

0.11.3 - 2023-04-24

Enhancements

#[derive(FromQueryResult)]
struct GenericTest<T: TryGetable> {
    foo: i32,
    bar: T,
}
trait MyTrait {
    type Item: TryGetable;
}

#[derive(FromQueryResult)]
struct TraitAssociateTypeTest<T>
where
    T: MyTrait,
{
    foo: T::Item,
}

Bug Fixes

0.11.2 - 2023-03-25

Enhancements

0.11.1 - 2023-03-10

Bug Fixes

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "binary")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    #[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
    pub binary: Vec<u8>,
    #[sea_orm(column_type = "Binary(BlobSize::Blob(Some(10)))")]
    pub binary_10: Vec<u8>,
    #[sea_orm(column_type = "Binary(BlobSize::Tiny)")]
    pub binary_tiny: Vec<u8>,
    #[sea_orm(column_type = "Binary(BlobSize::Medium)")]
    pub binary_medium: Vec<u8>,
    #[sea_orm(column_type = "Binary(BlobSize::Long)")]
    pub binary_long: Vec<u8>,
    #[sea_orm(column_type = "VarBinary(10)")]
    pub var_binary: Vec<u8>,
}
  • The CLI command sea-orm-cli generate entity -u '<DB-URL>' --expanded-format will now generate the following code for each Binary or VarBinary columns in expanded format https://github.com/SeaQL/sea-orm/pull/1529
impl ColumnTrait for Column {
    type EntityName = Entity;
    fn def(&self) -> ColumnDef {
        match self {
            Self::Id => ColumnType::Integer.def(),
            Self::Binary => ColumnType::Binary(sea_orm::sea_query::BlobSize::Blob(None)).def(),
            Self::Binary10 => {
                ColumnType::Binary(sea_orm::sea_query::BlobSize::Blob(Some(10u32))).def()
            }
            Self::BinaryTiny => ColumnType::Binary(sea_orm::sea_query::BlobSize::Tiny).def(),
            Self::BinaryMedium => ColumnType::Binary(sea_orm::sea_query::BlobSize::Medium).def(),
            Self::BinaryLong => ColumnType::Binary(sea_orm::sea_query::BlobSize::Long).def(),
            Self::VarBinary => ColumnType::VarBinary(10u32).def(),
        }
    }
}

0.11.0 - 2023-02-07

  • 2023-02-02: 0.11.0-rc.1
  • 2023-02-04: 0.11.0-rc.2

New Features

SeaORM Core

SeaORM CLI

SeaORM Migration

Enhancements

Upgrades

House Keeping

Bug Fixes

Breaking Changes

// then
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError>;
// now; ColIdx can be `&str` or `usize`
fn try_get_by<I: ColIdx>(res: &QueryResult, index: I) -> Result<Self, TryGetError>;

So if you implemented it yourself:

impl TryGetable for XXX {
-   fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
+   fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
-       let value: YYY = res.try_get(pre, col).map_err(TryGetError::DbErr)?;
+       let value: YYY = res.try_get_by(idx).map_err(TryGetError::DbErr)?;
        ..
    }
}
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
    async fn before_save<C>(self, db: &C, insert: bool) -> Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        // ...
    }

    // ...
}
let res = Update::one(cake::ActiveModel {
        name: Set("Cheese Cake".to_owned()),
        ..model.into_active_model()
    })
    .exec(&db)
    .await;

// then
assert_eq!(
    res,
    Err(DbErr::RecordNotFound(
        "None of the database rows are affected".to_owned()
    ))
);

// now
assert_eq!(res, Err(DbErr::RecordNotUpdated));
  • sea_orm::ColumnType was replaced by sea_query::ColumnType https://github.com/SeaQL/sea-orm/pull/1395
    • Method ColumnType::def was moved to ColumnTypeTrait
    • ColumnType::Binary becomes a tuple variant which takes in additional option sea_query::BlobSize
    • ColumnType::Custom takes a sea_query::DynIden instead of String and thus a new method custom is added (note the lowercase)
// Compact Entity
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "fruit")]
pub struct Model {
-   #[sea_orm(column_type = r#"Custom("citext".to_owned())"#)]
+   #[sea_orm(column_type = r#"custom("citext")"#)]
    pub column: String,
}
// Expanded Entity
impl ColumnTrait for Column {
    type EntityName = Entity;

    fn def(&self) -> ColumnDef {
        match self {
-           Self::Column => ColumnType::Custom("citext".to_owned()).def(),
+           Self::Column => ColumnType::custom("citext").def(),
        }
    }
}

Miscellaneous

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.10.0...0.11.0

0.10.7 - 2023-01-19

Bug Fixes

0.10.6 - 2022-12-23

Enhancements

Bug Fixes

0.10.5 - 2022-12-02

New Features

Bug Fixes

Enhancements

0.10.4 - 2022-11-24

Bug Fixes

Enhancements

0.10.3 - 2022-11-14

Bug Fixes

Enhancements

House Keeping

0.10.2 - 2022-11-06

Enhancements

Bug Fixes

Upgrades

  • Update MSRV to 1.65

0.10.1 - 2022-10-27

Enhancements

Bug Fixes

House Keeping

Upgrades

0.10.0 - 2022-10-23

New Features

Enhancements

Bug Fixes

Breaking Changes

enum ColumnType {
    // then
    Enum(String, Vec<String>)

    // now
    Enum {
        /// Name of enum
        name: DynIden,
        /// Variants of enum
        variants: Vec<DynIden>,
    }
    ...
}

// example

#[derive(Iden)]
enum TeaEnum {
    #[iden = "tea"]
    Enum,
    #[iden = "EverydayTea"]
    EverydayTea,
    #[iden = "BreakfastTea"]
    BreakfastTea,
}

// then
ColumnDef::new(active_enum_child::Column::Tea)
    .enumeration("tea", vec!["EverydayTea", "BreakfastTea"])

// now
ColumnDef::new(active_enum_child::Column::Tea)
    .enumeration(TeaEnum::Enum, [TeaEnum::EverydayTea, TeaEnum::BreakfastTea])
  • A new method array_type was added to ValueType:
impl sea_orm::sea_query::ValueType for MyType {
    fn array_type() -> sea_orm::sea_query::ArrayType {
        sea_orm::sea_query::ArrayType::TypeName
    }
    ...
}
  • ActiveEnum::name() changed return type to DynIden:
#[derive(Debug, Iden)]
#[iden = "category"]
pub struct CategoryEnum;

impl ActiveEnum for Category {
    // then
    fn name() -> String {
        "category".to_owned()
    }

    // now
    fn name() -> DynIden {
        SeaRc::new(CategoryEnum)
    }
    ...
}

House Keeping

Integration

Upgrades

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.9.0...0.10.0

0.9.3 - 2022-09-30

Enhancements

Bug Fixes

0.9.2 - 2022-08-20

Enhancements

House Keeping

Notes

In this minor release, we removed time v0.1 from the dependency graph

0.9.1 - 2022-07-22

Enhancements

Bug Fixes

House Keeping

0.9.0 - 2022-07-17

New Features

Enhancements

Upgrades

House Keeping

Bug Fixes

Breaking Changes

  • SelectTwoMany::one() has been dropped https://github.com/SeaQL/sea-orm/pull/813, you can get (Entity, Vec<RelatedEntity>) by first querying a single model from Entity, then use [ModelTrait::find_related] on the model.
  • Feature flag revamp

    We now adopt the weak dependency syntax in Cargo. That means the flags ["sqlx-json", "sqlx-chrono", "sqlx-decimal", "sqlx-uuid", "sqlx-time"] are not needed and now removed. Instead, with-time will enable sqlx?/time only if sqlx is already enabled. As a consequence, now the features with-json, with-chrono, with-rust_decimal, with-uuid, with-time will not be enabled as a side-effect of enabling sqlx.

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.8.0...0.9.0

sea-orm-migration 0.8.3

0.8.0 - 2022-05-10

New Features

Enhancements

Bug Fixes

Breaking Changes

  • Migration utilities are moved from sea-schema to sea-orm repo, under a new sub-crate sea-orm-migration. sea_schema::migration::prelude should be replaced by sea_orm_migration::prelude in all migration files

Upgrades

Fixed Issues

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.7.1...0.8.0

0.7.1 - 2022-03-26

  • Fix sea-orm-cli error
  • Fix sea-orm cannot build without with-json

0.7.0 - 2022-03-26

New Features

Enhancements

Bug Fixes

Breaking Changes

  • Exclude mock from default features by @billy1624 https://github.com/SeaQL/sea-orm/pull/562
  • create_table_from_entity will no longer create index for MySQL, please use the new method create_index_from_entity

Documentations

Fixed Issues

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.6.0...0.7.0

0.6.0 - 2022-02-07

New Features

Enhancements

Bug Fixes

Breaking Changes

Fixed Issues

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.5.0...0.6.0

0.5.0 - 2022-01-01

Fixed Issues

Merged PRs

Breaking Changes

  • ActiveModel::insert and ActiveModel::update return Model instead of ActiveModel
  • Method ActiveModelBehavior::after_save takes Model as input instead of ActiveModel
  • Rename method sea_orm::unchanged_active_value_not_intended_for_public_use to sea_orm::Unchanged
  • Rename method ActiveValue::unset to ActiveValue::not_set
  • Rename method ActiveValue::is_unset to ActiveValue::is_not_set
  • PartialEq of ActiveValue will also check the equality of state instead of just checking the equality of value

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.4.2...0.5.0

0.4.2 - 2021-12-12

Fixed Issues

Merged PRs

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.4.1...0.4.2

0.4.1 - 2021-12-05

Fixed Issues

Merged PRs

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.4.0...0.4.1

0.4.0 - 2021-11-19

Fixed Issues

Merged PRs

Breaking Changes

  • Refactor paginate() & count() utilities into PaginatorTrait. You can use the paginator as usual but you might need to import PaginatorTrait manually when upgrading from the previous version.
    use futures::TryStreamExt;
    use sea_orm::{entity::*, query::*, tests_cfg::cake};
    
    let mut cake_stream = cake::Entity::find()
        .order_by_asc(cake::Column::Id)
        .paginate(db, 50)
        .into_stream();
    
    while let Some(cakes) = cake_stream.try_next().await? {
        // Do something on cakes: Vec<cake::Model>
    }
    
  • The helper struct Schema converting EntityTrait into different sea-query statements now has to be initialized with DbBackend.
    use sea_orm::{tests_cfg::*, DbBackend, Schema};
    use sea_orm::sea_query::TableCreateStatement;
    
    // 0.3.x
    let _: TableCreateStatement = Schema::create_table_from_entity(cake::Entity);
    
    // 0.4.x
    let schema: Schema = Schema::new(DbBackend::MySql);
    let _: TableCreateStatement = schema.create_table_from_entity(cake::Entity);
    
  • When performing insert or update operation on ActiveModel against PostgreSQL, RETURNING clause will be used to perform select in a single SQL statement.
    // For PostgreSQL
    cake::ActiveModel {
        name: Set("Apple Pie".to_owned()),
        ..Default::default()
    }
    .insert(&postgres_db)
    .await?;
    
    assert_eq!(
        postgres_db.into_transaction_log(),
        vec![Transaction::from_sql_and_values(
            DbBackend::Postgres,
            r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id", "name""#,
            vec!["Apple Pie".into()]
        )]);
    
    // For MySQL & SQLite
    cake::ActiveModel {
        name: Set("Apple Pie".to_owned()),
        ..Default::default()
    }
    .insert(&other_db)
    .await?;
    
    assert_eq!(
        other_db.into_transaction_log(),
        vec![
            Transaction::from_sql_and_values(
                DbBackend::MySql,
                r#"INSERT INTO `cake` (`name`) VALUES (?)"#,
                vec!["Apple Pie".into()]
            ),
            Transaction::from_sql_and_values(
                DbBackend::MySql,
                r#"SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = ? LIMIT ?"#,
                vec![15.into(), 1u64.into()]
            )]);
    

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.3.2...0.4.0

0.3.2 - 2021-11-03

Fixed Issues

Merged PRs

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.3.1...0.3.2

0.3.1 - 2021-10-23

(We are changing our Changelog format from now on)

Fixed Issues

(The following is generated by GitHub)

Merged PRs

Full Changelog: https://github.com/SeaQL/sea-orm/compare/0.3.0...0.3.1

0.3.0 - 2021-10-15

https://www.sea-ql.org/SeaORM/blog/2021-10-15-whats-new-in-0.3.0

  • Built-in Rocket support
  • ConnectOptions
let mut opt = ConnectOptions::new("protocol://username:password@host/database".to_owned());
opt.max_connections(100)
    .min_connections(5)
    .connect_timeout(Duration::from_secs(8))
    .idle_timeout(Duration::from_secs(8));
let db = Database::connect(opt).await?;
  • [#211] Throw error if none of the db rows are affected
assert_eq!(
    Update::one(cake::ActiveModel {
        name: Set("Cheese Cake".to_owned()),
        ..model.into_active_model()
    })
    .exec(&db)
    .await,
    Err(DbErr::RecordNotFound(
        "None of the database rows are affected".to_owned()
    ))
);

// update many remains the same
assert_eq!(
    Update::many(cake::Entity)
        .col_expr(cake::Column::Name, Expr::value("Cheese Cake".to_owned()))
        .filter(cake::Column::Id.eq(2))
        .exec(&db)
        .await,
    Ok(UpdateResult { rows_affected: 0 })
);
  • [#223] ActiveValue::take() & ActiveValue::into_value() without unwrap()
  • [#205] Drop Default trait bound of PrimaryKeyTrait::ValueType
  • [#222] Transaction & streaming
  • [#210] Update ActiveModelBehavior API
  • [#240] Add derive DeriveIntoActiveModel and IntoActiveValue trait
  • [#237] Introduce optional serde support for model code generation
  • [#246] Add #[automatically_derived] to all derived implementations

0.2.6 - 2021-10-09

  • [#224] [sea-orm-cli] Date & Time column type mapping
  • Escape rust keywords with r# raw identifier

0.2.5 - 2021-10-06

  • [#227] Resolve "Inserting actual none value of Option results in panic"
  • [#219] [sea-orm-cli] Add --tables option
  • [#189] Add debug_query and debug_query_stmt macro

0.2.4 - 2021-10-01

https://www.sea-ql.org/SeaORM/blog/2021-10-01-whats-new-in-0.2.4

  • [#186] [sea-orm-cli] Foreign key handling
  • [#191] [sea-orm-cli] Unique key handling
  • [#182] find_linked join with alias
  • [#202] Accept both postgres:// and postgresql://
  • [#208] Support fetching T, (T, U), (T, U, P) etc
  • [#209] Rename column name & column enum variant
  • [#207] Support chrono::NaiveDate & chrono::NaiveTime
  • Support Condition::not (from sea-query)

0.2.3 - 2021-09-22

  • [#152] DatabaseConnection impl Clone
  • [#175] Impl TryGetableMany for different types of generics
  • Codegen TimestampWithTimeZone fixup

0.2.2 - 2021-09-18

  • [#105] Compact entity format
  • [#132] Add ActiveModel insert & update
  • [#129] Add set method to UpdateMany
  • [#118] Initial lock support
  • [#167] Add FromQueryResult::find_by_statement

0.2.1 - 2021-09-04

  • Update dependencies

0.2.0 - 2021-09-03

  • [#37] Rocket example
  • [#114] log crate and env-logger
  • [#103] InsertResult to return the primary key's type
  • [#89] Represent several relations between same types by Linked
  • [#59] Transforming an Entity into TableCreateStatement

0.1.3 - 2021-08-30

  • [#108] Remove impl TryGetable for Option

0.1.2 - 2021-08-23

  • [#68] Added DateTimeWithTimeZone as supported attribute type
  • [#70] Generate arbitrary named entity
  • [#80] Custom column name
  • [#81] Support join on multiple columns
  • [#99] Implement FromStr for ColumnTrait

0.1.1 - 2021-08-08

  • Early release of SeaORM