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 ofDynIden
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 errorsSqlErr
, 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(_))
));
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 thecolumn_type
andarray_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 implementsstd::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
inDeriveEntityModel
#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 implementseaography::RelationBuilder
forRelatedEntity
enumeration when theseaography
feature is enabled -
Added generation of
seaography
related information tosea-orm-codegen
.The
RelatedEntity
enum is added in entities files bysea-orm-cli
when flagseaography
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,
}
- Added
seaography_example
Enhancements
- Supports for partial select of
Option<T>
model field. ANone
value will be filled when the select result does not contain theOption<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 createm20230503_000000_create_accounts_table.rs
for you #1570 - Added
Migration::name()
andMigration::status()
getters for the name and status ofsea_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 whensqlx-postgres
backend is selected #1565 - Replace
String
parameters in API withInto<String>
#1439- Implements
IntoMockRow
for anyBTreeMap
that is indexed by stringimpl 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()
andColumnTrait::contains()
to takes any string
- Implements
- Added
sea_query::{DynIden, RcOrArc, SeaRc}
to entity prelude #1661 - Added
expr
,exprs
andexpr_as
methods toQuerySelect
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 becausestring_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>
withvia
andto
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 implementColumnTypeTrait
#1576 - Resolved
insert_many
failing if the models iterator is empty #873
Breaking changes
- Supports for partial select of
Option<T>
model field. ANone
value will be filled when the select result does not contain theOption<T>
field instead of throwing an error. #1513 - Replaced
sea-strum
dependency with upstreamstrum
insea-orm
#1535- Added
derive
andstrum
features tosea-orm-macros
- The derive macro
EnumIter
is now shipped bysea-orm-macros
- Added
- Added a new variant
Many
toIdentity
#1508 - Enabled
hashable-value
feature in SeaQuery, thusValue::Float(NaN) == Value::Float(NaN)
would be true #1728, #1743 - The
DeriveActiveEnum
derive macro no longer implementstd::fmt::Display
. You can use the newDeriveDisplay
macro #1726 sea-query/derive
is no longer enabled bysea-orm
, as such,Iden
no longer works as a derive macro (it's still a trait). Instead, we are shipping a new macroDeriveIden
#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 toConnectionAcquire(ConnAcquireErr)
#1737 FromJsonQueryResult
removed from entity prelude
Upgrades
- Upgraded
sqlx
to0.7
#1742 - Upgraded
sea-query
to0.30
#1742 - Upgraded
sea-schema
to0.14
#1742 - Upgraded
syn
to2
#1713 - Upgraded
heck
to0.4
#1520, #1544 - Upgraded
strum
to0.25
#1752 - Upgraded
clap
to4.3
#1468 - Upgraded
ouroboros
to0.17
#1724
House keeping
- Replaced
bae
withsea-bae
#1739
New Contributors
- @sergeiivankov made their first contribution in #1520
- @Reverier-Xu made their first contribution in #1513
- @y3ll0wlife made their first contribution in #1547
- @langyo made their first contribution in #1546
- @AfaanBilal made their first contribution in #1545
- @jacobtread made their first contribution in #1550
- @rito528 made their first contribution in #1553
- @sanihaq made their first contribution in #1334
- @denwong47 made their first contribution in #1374
- @atopx made their first contribution in #1567
- @aumetra made their first contribution in #1572
- @ZihanType made their first contribution in #1580
- @leviska made their first contribution in #1464
- @jared-mackey made their first contribution in #1585
- @babalolajnr made their first contribution in #1570
- @df51d made their first contribution in #1662
- @Outurnate made their first contribution in #1681
- @ProbablyClem made their first contribution in #1627
- @aadi58002 made their first contribution in #1468
- @EETagent made their first contribution in #1686
- @AlvaroParker made their first contribution in #1685
- @GRA0007 made their first contribution in #1697
- @darkmmon made their first contribution in #1702
- @ccqpein made their first contribution in #1723
- @joelhy made their first contribution in #1731
- @niklaskorz made their first contribution in #1678
- @aidalgol made their first contribution in #1775
- @vicanso made their first contribution in #1729
- @mgugger made their first contribution in #1761
Full Changelog: 0.11.1...0.12.1