github SeaQL/sea-orm 0.12.1

latest releases: 1.1.1, 1.1.0, 1.1.0-rc.3...
15 months ago

New Features

  • Added MigratorTrait::migration_table_name() method to configure the name of migration table #1511
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
    // Override the name of migration table
    fn migration_table_name() -> sea_orm::DynIden {
        Alias::new("override_migration_table_name").into_iden()
    }
    ...
}
  • Added option to construct chained AND / OR join on condition #1433
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cake")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    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,
}
  • Supports entity with composite primary key of arity 12 #1508
    • Identity supports tuple of DynIden with arity up to 12
#[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_12: bool,
}
  • Added macro DerivePartialModel #1597
#[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""#
);
  • Added DbErr::sql_err() method to convert error into common database errors SqlErr, such as unique constraint or foreign key violation errors. #1707
assert!(matches!(
    cake.into_active_model().insert(db).await
        .expect_err("Insert a row with duplicated primary key")
        .sql_err(),
    Some(SqlErr::UniqueConstraintViolation(_))
));

assert!(matches!(
    fk_cake.insert(db).await
        .expect_err("Insert a row with invalid foreign key")
        .sql_err(),
    Some(SqlErr::ForeignKeyConstraintViolation(_))
));
  • Added Select::find_with_linked, similar to find_with_related: #1728, #1743
fn find_with_related<R>(self, r: R) -> SelectTwoMany<E, R>
    where R: EntityTrait, E: Related<R>;
fn find_with_linked<L, T>(self, l: L) -> SelectTwoMany<E, T>
    where L: Linked<FromEntity = E, ToEntity = T>, T: EntityTrait;

// boths yields `Vec<(E::Model, Vec<F::Model>)>`
  • Added DeriveValueType derive macro for custom wrapper types, implementations of the required traits will be provided, you can customize the column_type and array_type if needed #1720
#[derive(DeriveValueType)]
#[sea_orm(array_type = "Int")]
pub struct Integer(i32);

#[derive(DeriveValueType)]
#[sea_orm(column_type = "Boolean", array_type = "Bool")]
pub struct Boolbean(pub String);

#[derive(DeriveValueType)]
pub struct StringVec(pub Vec<String>);
  • Added DeriveDisplay derive macro to implements std::fmt::Display for enum #1726
#[derive(DeriveDisplay)]
enum DisplayTea {
    EverydayTea,
    #[sea_orm(display_value = "Breakfast Tea")]
    BreakfastTea,
}
assert_eq!(format!("{}", DisplayTea::EverydayTea), "EverydayTea");
assert_eq!(format!("{}", DisplayTea::BreakfastTea), "Breakfast Tea");
  • Added UpdateMany::exec_with_returning() #1677
let models: Vec<Model> = Entity::update_many()
    .col_expr(Column::Values, Expr::expr(..))
    .exec_with_returning(db)
    .await?;
  • Supporting default_expr in DeriveEntityModel #1474
#[derive(DeriveEntityModel)]
#[sea_orm(table_name = "hello")]
pub struct Model {
    #[sea_orm(default_expr = "Expr::current_timestamp()")]
    pub timestamp: DateTimeUtc,
}

assert_eq!(
    Column::Timestamp.def(),
    ColumnType::TimestampWithTimeZone.def()
        .default(Expr::current_timestamp())
);
  • Introduced new ConnAcquireErr #1737
enum DbErr {
    ConnectionAcquire(ConnAcquireErr),
    ..
}

enum ConnAcquireErr {
    Timeout,
    ConnectionClosed,
}

Seaography

Added Seaography integration #1599

  • Added DeriveEntityRelated macro which will implement seaography::RelationBuilder for RelatedEntity enumeration when the seaography feature is enabled

  • Added generation of seaography related information to sea-orm-codegen.

    The RelatedEntity enum is added in entities files by sea-orm-cli when flag seaography is set:

/// SeaORM Entity
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelatedEntity)]
pub enum RelatedEntity {
    #[sea_orm(entity = "super::bakery::Entity")]
    Bakery,
    #[sea_orm(entity = "super::cake_baker::Entity")]
    CakeBaker,
    #[sea_orm(entity = "super::cake::Entity")]
    Cake,
}

Enhancements

  • 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. #1513
  • [sea-orm-cli] the migrate init command will create a .gitignore file when the migration folder reside in a Git repository #1334
  • [sea-orm-cli] Added support for generating migration of space separated name, for example executing sea-orm-cli migrate generate "create accounts table" command will create m20230503_000000_create_accounts_table.rs for you #1570
  • Added Migration::name() and Migration::status() getters for the name and status of sea_orm_migration::Migration #1519
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 #1565
  • Replace String parameters in API with Into<String> #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
  • Added sea_query::{DynIden, RcOrArc, SeaRc} to entity prelude #1661
  • Added expr, exprs and expr_as methods to QuerySelect trait #1702
  • Added DatabaseConnection::ping #1627
|db: DatabaseConnection| {
    assert!(db.ping().await.is_ok());
    db.clone().close().await;
    assert!(matches!(db.ping().await, Err(DbErr::ConnectionAcquire)));
}
  • Added TryInsert that does not panic on empty inserts #1708
// now, you can do:
let res = Bakery::insert_many(std::iter::empty())
    .on_empty_do_nothing()
    .exec(db)
    .await;

assert!(matches!(res, Ok(TryInsertResult::Empty)));
  • Insert on conflict do nothing to return Ok #1712
let on = OnConflict::column(Column::Id).do_nothing().to_owned();

// Existing behaviour
let res = Entity::insert_many([..]).on_conflict(on).exec(db).await;
assert!(matches!(res, Err(DbErr::RecordNotInserted)));

// New API; now you can:
let res =
Entity::insert_many([..]).on_conflict(on).do_nothing().exec(db).await;
assert!(matches!(res, Ok(TryInsertResult::Conflicted)));

Bug Fixes

  • Fixed DeriveActiveEnum throwing errors because string_value consists non-UAX#31 compliant characters #1374
#[derive(DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "String(None)")]
pub enum StringValue {
    #[sea_orm(string_value = "")]
    Member1,
    #[sea_orm(string_value = "$$")]
    Member2,
}
// will now produce the following enum:
pub enum StringValueVariant {
    __Empty,
    _0x240x24,
}
  • [sea-orm-cli] Fix Postgres enum arrays #1678
  • [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 #1435
  • [sea-orm-cli] fixed entity generation includes partitioned tables #1582, SeaQL/sea-schema#105
  • Fixed ActiveEnum::db_type() return type does not implement ColumnTypeTrait #1576
  • Resolved insert_many failing if the models iterator is empty #873

Breaking changes

  • 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 instead of throwing an error. #1513
  • Replaced sea-strum dependency with upstream strum in sea-orm #1535
    • Added derive and strum features to sea-orm-macros
    • The derive macro EnumIter is now shipped by sea-orm-macros
  • Added a new variant Many to Identity #1508
  • Enabled hashable-value feature in SeaQuery, thus Value::Float(NaN) == Value::Float(NaN) would be true #1728, #1743
  • The DeriveActiveEnum derive macro no longer implement std::fmt::Display. You can use the new DeriveDisplay macro #1726
  • sea-query/derive is no longer enabled by sea-orm, as such, Iden no longer works as a derive macro (it's still a trait). Instead, we are shipping a new macro DeriveIden #1740 #1755
// then:

#[derive(Iden)]
#[iden = "category"]
pub struct CategoryEnum;

#[derive(Iden)]
pub enum Tea {
    Table,
    #[iden = "EverydayTea"]
    EverydayTea,
}

// now:

#[derive(DeriveIden)]
#[sea_orm(iden = "category")]
pub struct CategoryEnum;

#[derive(DeriveIden)]
pub enum Tea {
    Table,
    #[sea_orm(iden = "EverydayTea")]
    EverydayTea,
}
  • Definition of DbErr::ConnectionAcquire changed to ConnectionAcquire(ConnAcquireErr) #1737
  • FromJsonQueryResult removed from entity prelude

Upgrades

  • Upgraded sqlx to 0.7 #1742
  • Upgraded sea-query to 0.30 #1742
  • Upgraded sea-schema to 0.14 #1742
  • Upgraded syn to 2 #1713
  • Upgraded heck to 0.4 #1520, #1544
  • Upgraded strum to 0.25 #1752
  • Upgraded clap to 4.3 #1468
  • Upgraded ouroboros to 0.17 #1724

House keeping

  • Replaced bae with sea-bae #1739

New Contributors

Full Changelog: 0.11.1...0.12.1

Don't miss a new sea-orm release

NewReleases is sending notifications on new releases.