Changelog
This commit is contained in:
parent
3629b91d01
commit
7352008e0e
276
CHANGELOG.md
276
CHANGELOG.md
@ -14,45 +14,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
### New Features
|
### 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
|
|
||||||
```rust
|
|
||||||
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);
|
|
||||||
```
|
|
||||||
* [sea-orm-cli] the `migrate init` command will create a `.gitignore` file when the migration folder reside in a Git repository https://github.com/SeaQL/sea-orm/pull/1334
|
|
||||||
* Added `MigratorTrait::migration_table_name()` method to configure the name of migration table https://github.com/SeaQL/sea-orm/pull/1511
|
* Added `MigratorTrait::migration_table_name()` method to configure the name of migration table https://github.com/SeaQL/sea-orm/pull/1511
|
||||||
```rust
|
```rust
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl MigratorTrait for Migrator {
|
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
|
// Override the name of migration table
|
||||||
fn migration_table_name() -> sea_orm::DynIden {
|
fn migration_table_name() -> sea_orm::DynIden {
|
||||||
Alias::new("override_migration_table_name").into_iden()
|
Alias::new("override_migration_table_name").into_iden()
|
||||||
}
|
}
|
||||||
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
* Added option to construct chained AND / OR join on condition https://github.com/SeaQL/sea-orm/pull/1433
|
* Added option to construct chained AND / OR join on condition https://github.com/SeaQL/sea-orm/pull/1433
|
||||||
@ -64,7 +34,6 @@ use sea_orm::entity::prelude::*;
|
|||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
#[sea_orm(column_name = "name", enum_name = "Name")]
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,40 +55,6 @@ pub enum Relation {
|
|||||||
)]
|
)]
|
||||||
OrTropicalFruit,
|
OrTropicalFruit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
||||||
```
|
|
||||||
You can also override it in custom join.
|
|
||||||
```rust
|
|
||||||
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(" ")
|
|
||||||
);
|
|
||||||
```
|
```
|
||||||
* Supports entity with composite primary key of length 12 https://github.com/SeaQL/sea-orm/pull/1508
|
* Supports entity with composite primary key of length 12 https://github.com/SeaQL/sea-orm/pull/1508
|
||||||
* Implemented `IntoIdentity` for `Identity` https://github.com/SeaQL/sea-orm/pull/1508
|
* Implemented `IntoIdentity` for `Identity` https://github.com/SeaQL/sea-orm/pull/1508
|
||||||
@ -136,37 +71,10 @@ use sea_orm::entity::prelude::*;
|
|||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
pub id_1: String,
|
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)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
pub id_12: bool,
|
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 {}
|
|
||||||
```
|
```
|
||||||
* Added macro `DerivePartialModel` https://github.com/SeaQL/sea-orm/pull/1597
|
* Added macro `DerivePartialModel` https://github.com/SeaQL/sea-orm/pull/1597
|
||||||
```rust
|
```rust
|
||||||
@ -188,31 +96,6 @@ assert_eq!(
|
|||||||
r#"SELECT "cake"."name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
|
r#"SELECT "cake"."name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
* [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 https://github.com/SeaQL/sea-orm/pull/1570
|
|
||||||
|
|
||||||
* Add `seaography` flag to `sea-orm`, `sea-orm-orm-macros` and `sea-orm-cli` https://github.com/SeaQL/sea-orm/pull/1599
|
|
||||||
* Add generation of `seaography` related information to `sea-orm-codegen` https://github.com/SeaQL/sea-orm/pull/1599
|
|
||||||
|
|
||||||
The following information is added in entities files by `sea-orm-cli` when flag `seaography` is `true`
|
|
||||||
```rust
|
|
||||||
/// ... 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
|
* 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
|
The DeriveRelatedEntity derive macro will implement `seaography::RelationBuilder` for `RelatedEntity` enumeration when the `seaography` feature is enabled
|
||||||
@ -297,91 +180,91 @@ pub struct Boolbean(pub String);
|
|||||||
#[derive(DeriveValueType)]
|
#[derive(DeriveValueType)]
|
||||||
pub struct StringVec(pub Vec<String>);
|
pub struct StringVec(pub Vec<String>);
|
||||||
```
|
```
|
||||||
The expanded code of `DeriveValueType` looks like.
|
|
||||||
```rust
|
|
||||||
#[derive(DeriveValueType)]
|
|
||||||
pub struct StringVec(pub Vec<String>);
|
|
||||||
|
|
||||||
// The `DeriveValueType` will be expanded into...
|
|
||||||
|
|
||||||
impl From<StringVec> for Value {
|
|
||||||
fn from(source: StringVec) -> Self {
|
|
||||||
source.0.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl sea_orm::TryGetable for StringVec {
|
|
||||||
fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, sea_orm::TryGetError> {
|
|
||||||
<Vec<String> as sea_orm::TryGetable>::try_get_by(res, idx).map(|v| StringVec(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl sea_orm::sea_query::ValueType for StringVec {
|
|
||||||
fn try_from(v: Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> {
|
|
||||||
<Vec<String> as sea_orm::sea_query::ValueType>::try_from(v).map(|v| StringVec(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_name() -> String {
|
|
||||||
stringify!(StringVec).to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn array_type() -> sea_orm::sea_query::ArrayType {
|
|
||||||
std::convert::Into::<sea_orm::sea_query::ArrayType>::into(
|
|
||||||
<Vec<String> as sea_orm::sea_query::ValueType>::array_type()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn column_type() -> sea_orm::sea_query::ColumnType {
|
|
||||||
std::convert::Into::<sea_orm::sea_query::ColumnType>::into(
|
|
||||||
<Vec<String> as sea_orm::sea_query::ValueType>::column_type()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Add `DeriveDisplay` derive macro to implements `std::fmt::Display` for active enum https://github.com/SeaQL/sea-orm/pull/1726
|
* Add `DeriveDisplay` derive macro to implements `std::fmt::Display` for active enum https://github.com/SeaQL/sea-orm/pull/1726
|
||||||
```rust
|
```rust
|
||||||
// String enum
|
#[derive(DeriveDisplay)]
|
||||||
#[derive(EnumIter, DeriveActiveEnum, DeriveDisplay)]
|
|
||||||
#[sea_orm(rs_type = "String", db_type = "String(Some(1))", enum_name = "category")]
|
|
||||||
pub enum DeriveCategory {
|
|
||||||
#[sea_orm(string_value = "B")]
|
|
||||||
Big,
|
|
||||||
#[sea_orm(string_value = "S")]
|
|
||||||
Small,
|
|
||||||
}
|
|
||||||
assert_eq!(format!("{}", DeriveCategory::Big), "Big");
|
|
||||||
assert_eq!(format!("{}", DeriveCategory::Small), "Small");
|
|
||||||
|
|
||||||
// Numeric enum
|
|
||||||
#[derive(EnumIter, DeriveActiveEnum, DeriveDisplay)]
|
|
||||||
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
|
||||||
pub enum $ident {
|
|
||||||
#[sea_orm(num_value = -10)]
|
|
||||||
Negative,
|
|
||||||
#[sea_orm(num_value = 1)]
|
|
||||||
Big,
|
|
||||||
#[sea_orm(num_value = 0)]
|
|
||||||
Small,
|
|
||||||
}
|
|
||||||
assert_eq!(format!("{}", $ident::Big), "Big");
|
|
||||||
assert_eq!(format!("{}", $ident::Small), "Small");
|
|
||||||
assert_eq!(format!("{}", $ident::Negative), "Negative");
|
|
||||||
|
|
||||||
// String enum with `display_value` overrides
|
|
||||||
#[derive(EnumIter, DeriveActiveEnum, DeriveDisplay)]
|
|
||||||
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")]
|
|
||||||
pub enum DisplayTea {
|
pub enum DisplayTea {
|
||||||
#[sea_orm(string_value = "EverydayTea", display_value = "Everyday")]
|
|
||||||
EverydayTea,
|
EverydayTea,
|
||||||
#[sea_orm(string_value = "BreakfastTea", display_value = "Breakfast")]
|
#[sea_orm(display_value = "Breakfast")]
|
||||||
BreakfastTea,
|
BreakfastTea,
|
||||||
}
|
}
|
||||||
|
assert_eq!(format!("{}", DisplayTea::EverydayTea), "EverydayTea");
|
||||||
assert_eq!(format!("{}", DisplayTea::BreakfastTea), "Breakfast");
|
assert_eq!(format!("{}", DisplayTea::BreakfastTea), "Breakfast");
|
||||||
assert_eq!(format!("{}", DisplayTea::EverydayTea), "Everyday");
|
```
|
||||||
|
* Added `UpdateMany::exec_with_returning()` https://github.com/SeaQL/sea-orm/pull/1677
|
||||||
|
```rust
|
||||||
|
Entity::update_many()
|
||||||
|
.col_expr(Column::Values, Expr::expr(..))
|
||||||
|
.exec_with_returning(db)
|
||||||
|
.await
|
||||||
|
```
|
||||||
|
* Supporting `default_expr` in `DeriveEntityModel` https://github.com/SeaQL/sea-orm/pull/1474
|
||||||
|
```rust
|
||||||
|
#[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())
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Seaography
|
||||||
|
|
||||||
|
* Add generation of `seaography` related information to `sea-orm-codegen` https://github.com/SeaQL/sea-orm/pull/1599
|
||||||
|
|
||||||
|
The following information is added in entities files by `sea-orm-cli` when flag `seaography` is `true`
|
||||||
|
```rust
|
||||||
|
/// ... 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,
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Enhancements
|
### 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. https://github.com/SeaQL/sea-orm/pull/1513
|
||||||
|
```rust
|
||||||
|
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);
|
||||||
|
```
|
||||||
|
* [sea-orm-cli] the `migrate init` command will create a `.gitignore` file when the migration folder reside in a Git repository https://github.com/SeaQL/sea-orm/pull/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 https://github.com/SeaQL/sea-orm/pull/1570
|
||||||
* Added `Migration::name()` and `Migration::status()` getters for the name and status of `sea_orm_migration::Migration` https://github.com/SeaQL/sea-orm/pull/1519
|
* Added `Migration::name()` and `Migration::status()` getters for the name and status of `sea_orm_migration::Migration` https://github.com/SeaQL/sea-orm/pull/1519
|
||||||
```rust
|
```rust
|
||||||
let migrations = Migrator::get_pending_migrations(db).await?;
|
let migrations = Migrator::get_pending_migrations(db).await?;
|
||||||
@ -432,13 +315,6 @@ assert!(matches!(res, Err(DbErr::RecordNotInserted)));
|
|||||||
let res = Entity::insert_many([..]).on_conflict(on).do_nothing().exec(db).await;
|
let res = Entity::insert_many([..]).on_conflict(on).do_nothing().exec(db).await;
|
||||||
assert!(matches!(res, Ok(TryInsertResult::Conflicted)));
|
assert!(matches!(res, Ok(TryInsertResult::Conflicted)));
|
||||||
```
|
```
|
||||||
* Added `UpdateMany::exec_with_returning()` https://github.com/SeaQL/sea-orm/pull/1677
|
|
||||||
```rust
|
|
||||||
Entity::update_many()
|
|
||||||
.col_expr(Column::Values, Expr::expr(..))
|
|
||||||
.exec_with_returning(db)
|
|
||||||
.await
|
|
||||||
```
|
|
||||||
|
|
||||||
### Upgrades
|
### Upgrades
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user