From f79a4171503dbcd6f86187b6263e7c345bd173be Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 27 Sep 2021 18:01:38 +0800 Subject: [PATCH 01/20] Remove `ValueType: Default` --- src/entity/active_model.rs | 25 +++++++++++-------------- src/entity/base_entity.rs | 8 ++++++-- src/entity/prelude.rs | 5 +++-- src/entity/primary_key.rs | 20 +++++++++++--------- src/executor/insert.rs | 29 ++++++++++++++++++++--------- src/query/insert.rs | 23 +++++++++++++++++++++-- 6 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index cfcb0bbd..c69e5b01 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -1,6 +1,6 @@ use crate::{ error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, - PrimaryKeyTrait, Value, + PrimaryKeyValue, Value, }; use async_trait::async_trait; use std::fmt::Debug; @@ -70,23 +70,18 @@ pub trait ActiveModelTrait: Clone + Debug { async fn insert(self, db: &DatabaseConnection) -> Result where ::Model: IntoActiveModel, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { let am = self; let exec = ::insert(am).exec(db); let res = exec.await?; - // Assume valid last_insert_id is not equals to Default::default() - if res.last_insert_id - != <::PrimaryKey as PrimaryKeyTrait>::ValueType::default() - { - let found = ::find_by_id(res.last_insert_id) - .one(db) - .await?; - match found { - Some(model) => Ok(model.into_active_model()), - None => Err(DbErr::Exec("Failed to find inserted item".to_owned())), - } - } else { - Ok(Self::default()) + let found = ::find_by_id(res.last_insert_id) + .one(db) + .await?; + match found { + Some(model) => Ok(model.into_active_model()), + None => Err(DbErr::Exec("Failed to find inserted item".to_owned())), } } @@ -101,6 +96,8 @@ pub trait ActiveModelTrait: Clone + Debug { where Self: ActiveModelBehavior, ::Model: IntoActiveModel, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { let mut am = self; am = ActiveModelBehavior::before_save(am); diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index 7ba1e965..0c9813f7 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -1,7 +1,7 @@ use crate::{ ActiveModelTrait, ColumnTrait, Delete, DeleteMany, DeleteOne, FromQueryResult, Insert, - ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, Related, RelationBuilder, - RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne, + ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, Related, + RelationBuilder, RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne, }; use sea_query::{Alias, Iden, IntoIden, IntoTableRef, IntoValueTuple, TableRef}; pub use sea_strum::IntoEnumIterator as Iterable; @@ -299,6 +299,8 @@ pub trait EntityTrait: EntityName { fn insert(model: A) -> Insert where A: ActiveModelTrait, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { Insert::one(model) } @@ -352,6 +354,8 @@ pub trait EntityTrait: EntityName { where A: ActiveModelTrait, I: IntoIterator, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { Insert::many(models) } diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs index 8d87a4b2..be630567 100644 --- a/src/entity/prelude.rs +++ b/src/entity/prelude.rs @@ -2,8 +2,9 @@ pub use crate::{ error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity, DeriveEntityModel, DeriveModel, DerivePrimaryKey, DeriveRelation, EntityName, EntityTrait, - EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, ModelTrait, PrimaryKeyToColumn, - PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, Value, + EnumIter, ForeignKeyAction, Iden, IdenStatic, IntoActiveModel, Linked, ModelTrait, + PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, QueryResult, Related, + RelationDef, RelationTrait, Select, Value, }; #[cfg(feature = "with-json")] diff --git a/src/entity/primary_key.rs b/src/entity/primary_key.rs index 463f1482..530eba30 100644 --- a/src/entity/primary_key.rs +++ b/src/entity/primary_key.rs @@ -1,18 +1,11 @@ use super::{ColumnTrait, IdenStatic, Iterable}; -use crate::{TryFromU64, TryGetableMany}; +use crate::{ActiveModelTrait, EntityTrait, TryFromU64, TryGetableMany}; use sea_query::IntoValueTuple; use std::fmt::Debug; //LINT: composite primary key cannot auto increment pub trait PrimaryKeyTrait: IdenStatic + Iterable { - type ValueType: Sized - + Send - + Default - + Debug - + PartialEq - + IntoValueTuple - + TryGetableMany - + TryFromU64; + type ValueType: Sized + Send + Debug + PartialEq + IntoValueTuple + TryGetableMany + TryFromU64; fn auto_increment() -> bool; } @@ -26,3 +19,12 @@ pub trait PrimaryKeyToColumn { where Self: Sized; } + +pub trait PrimaryKeyValue +where + E: EntityTrait, +{ + fn get_primary_key_value(active_model: A) -> ::ValueType + where + A: ActiveModelTrait; +} diff --git a/src/executor/insert.rs b/src/executor/insert.rs index 1f4936ba..cb7e5555 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -5,11 +5,12 @@ use crate::{ use sea_query::InsertStatement; use std::{future::Future, marker::PhantomData}; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Inserter where A: ActiveModelTrait, { + primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, query: InsertStatement, model: PhantomData, } @@ -48,7 +49,7 @@ where ); } } - Inserter::::new(query).exec(db) + Inserter::::new(self.primary_key, query).exec(db) // TODO: return primary key if extracted before, otherwise use InsertResult } } @@ -57,8 +58,12 @@ impl Inserter where A: ActiveModelTrait, { - pub fn new(query: InsertStatement) -> Self { + pub fn new( + primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, + query: InsertStatement, + ) -> Self { Self { + primary_key, query, model: PhantomData, } @@ -72,12 +77,13 @@ where A: 'a, { let builder = db.get_database_backend(); - exec_insert(builder.build(&self.query), db) + exec_insert(self.primary_key, builder.build(&self.query), db) } } // Only Statement impl Send async fn exec_insert( + primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, statement: Statement, db: &DatabaseConnection, ) -> Result, DbErr> @@ -86,7 +92,7 @@ where { type PrimaryKey = <::Entity as EntityTrait>::PrimaryKey; type ValueTypeOf = as PrimaryKeyTrait>::ValueType; - let last_insert_id = match db { + let last_insert_id_opt = match db { #[cfg(feature = "sqlx-postgres")] DatabaseConnection::SqlxPostgresPoolConnection(conn) => { use crate::{sea_query::Iden, Iterable}; @@ -94,14 +100,19 @@ where .map(|col| col.to_string()) .collect::>(); let res = conn.query_one(statement).await?.unwrap(); - res.try_get_many("", cols.as_ref()).unwrap_or_default() + Some(res.try_get_many("", cols.as_ref()).unwrap_or_default()) } _ => { let last_insert_id = db.execute(statement).await?.last_insert_id(); - ValueTypeOf::::try_from_u64(last_insert_id) - .ok() - .unwrap_or_default() + ValueTypeOf::::try_from_u64(last_insert_id).ok() } }; + let last_insert_id = match last_insert_id_opt { + Some(last_insert_id) => last_insert_id, + None => match primary_key { + Some(primary_key) => primary_key, + None => return Err(DbErr::Exec("Fail to unpack last_insert_id".to_owned())), + }, + }; Ok(InsertResult { last_insert_id }) } diff --git a/src/query/insert.rs b/src/query/insert.rs index a65071e1..418d2b70 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -1,14 +1,18 @@ -use crate::{ActiveModelTrait, EntityName, EntityTrait, IntoActiveModel, Iterable, QueryTrait}; +use crate::{ + ActiveModelTrait, EntityName, EntityTrait, IntoActiveModel, Iterable, PrimaryKeyTrait, + PrimaryKeyValue, QueryTrait, +}; use core::marker::PhantomData; use sea_query::InsertStatement; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Insert where A: ActiveModelTrait, { pub(crate) query: InsertStatement, pub(crate) columns: Vec, + pub(crate) primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, pub(crate) model: PhantomData, } @@ -31,6 +35,7 @@ where .into_table(A::Entity::default().table_ref()) .to_owned(), columns: Vec::new(), + primary_key: None, model: PhantomData, } } @@ -68,6 +73,8 @@ where pub fn one(m: M) -> Insert where M: IntoActiveModel, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { Self::new().add(m) } @@ -97,6 +104,8 @@ where where M: IntoActiveModel, I: IntoIterator, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { Self::new().add_many(models) } @@ -105,8 +114,16 @@ where pub fn add(mut self, m: M) -> Self where M: IntoActiveModel, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { let mut am: A = m.into_active_model(); + self.primary_key = + if !<::PrimaryKey as PrimaryKeyTrait>::auto_increment() { + Some(<::PrimaryKey as PrimaryKeyValue>::get_primary_key_value::(am.clone())) + } else { + None + }; let mut columns = Vec::new(); let mut values = Vec::new(); let columns_empty = self.columns.is_empty(); @@ -132,6 +149,8 @@ where where M: IntoActiveModel, I: IntoIterator, + <::Entity as EntityTrait>::PrimaryKey: + PrimaryKeyValue<::Entity>, { for model in models.into_iter() { self = self.add(model); From 4f090d192bf7a26024c60792cd0b9bfdddbda97b Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 27 Sep 2021 18:02:12 +0800 Subject: [PATCH 02/20] Update `DerivePrimaryKey` --- sea-orm-macros/src/derives/primary_key.rs | 30 +++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/sea-orm-macros/src/derives/primary_key.rs b/sea-orm-macros/src/derives/primary_key.rs index e677e2e6..ce7ca840 100644 --- a/sea-orm-macros/src/derives/primary_key.rs +++ b/sea-orm-macros/src/derives/primary_key.rs @@ -1,7 +1,7 @@ use heck::SnakeCase; use proc_macro2::{Ident, TokenStream}; -use quote::{quote, quote_spanned}; -use syn::{Data, DataEnum, Fields, Variant}; +use quote::{quote, quote_spanned, ToTokens}; +use syn::{punctuated::Punctuated, token::Comma, Data, DataEnum, Fields, Variant}; pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result { let variants = match data { @@ -30,6 +30,21 @@ pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result = + variants.iter().fold(Punctuated::new(), |mut acc, v| { + let variant = &v.ident; + acc.push( + quote! { active_model.take(#ident::#variant.into_column()).unwrap().unwrap() }, + ); + acc + }); + let mut primary_key_value = primary_key_value.to_token_stream(); + if variants.len() > 1 { + primary_key_value = quote! { + (#primary_key_value) + }; + } + Ok(quote!( impl sea_orm::Iden for #ident { fn unquoted(&self, s: &mut dyn std::fmt::Write) { @@ -61,5 +76,16 @@ pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result for #ident { + fn get_primary_key_value( + mut active_model: A, + ) -> <::PrimaryKey as PrimaryKeyTrait>::ValueType + where + A: ActiveModelTrait, + { + #primary_key_value + } + } )) } From 9efaeeba8b15f8f71c2565f55976ea26d84fb651 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 27 Sep 2021 18:02:20 +0800 Subject: [PATCH 03/20] Update test cases --- tests/crud/create_cake.rs | 6 +----- tests/crud/create_lineitem.rs | 6 +----- tests/crud/create_order.rs | 6 +----- tests/sequential_op_tests.rs | 12 ++---------- tests/uuid_tests.rs | 9 +-------- 5 files changed, 6 insertions(+), 33 deletions(-) diff --git a/tests/crud/create_cake.rs b/tests/crud/create_cake.rs index 4fa914a5..df5130aa 100644 --- a/tests/crud/create_cake.rs +++ b/tests/crud/create_cake.rs @@ -58,11 +58,7 @@ pub async fn test_create_cake(db: &DbConn) { .expect("could not insert cake_baker"); assert_eq!( cake_baker_res.last_insert_id, - if cfg!(feature = "sqlx-postgres") { - (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) - } else { - Default::default() - } + (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) ); assert!(cake.is_some()); diff --git a/tests/crud/create_lineitem.rs b/tests/crud/create_lineitem.rs index da82cc82..0ba9c7d3 100644 --- a/tests/crud/create_lineitem.rs +++ b/tests/crud/create_lineitem.rs @@ -57,11 +57,7 @@ pub async fn test_create_lineitem(db: &DbConn) { .expect("could not insert cake_baker"); assert_eq!( cake_baker_res.last_insert_id, - if cfg!(feature = "sqlx-postgres") { - (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) - } else { - Default::default() - } + (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) ); // Customer diff --git a/tests/crud/create_order.rs b/tests/crud/create_order.rs index ba8ff09b..6de3d46f 100644 --- a/tests/crud/create_order.rs +++ b/tests/crud/create_order.rs @@ -57,11 +57,7 @@ pub async fn test_create_order(db: &DbConn) { .expect("could not insert cake_baker"); assert_eq!( cake_baker_res.last_insert_id, - if cfg!(feature = "sqlx-postgres") { - (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) - } else { - Default::default() - } + (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) ); // Customer diff --git a/tests/sequential_op_tests.rs b/tests/sequential_op_tests.rs index 28333d84..286e856a 100644 --- a/tests/sequential_op_tests.rs +++ b/tests/sequential_op_tests.rs @@ -84,11 +84,7 @@ async fn init_setup(db: &DatabaseConnection) { .expect("could not insert cake_baker"); assert_eq!( cake_baker_res.last_insert_id, - if cfg!(feature = "sqlx-postgres") { - (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) - } else { - Default::default() - } + (cake_baker.cake_id.unwrap(), cake_baker.baker_id.unwrap()) ); let customer_kate = customer::ActiveModel { @@ -225,11 +221,7 @@ async fn create_cake(db: &DatabaseConnection, baker: baker::Model) -> Option Result<(), DbErr> { assert_eq!(Metadata::find().one(db).await?, Some(metadata.clone())); - assert_eq!( - res.last_insert_id, - if cfg!(feature = "sqlx-postgres") { - metadata.uuid - } else { - Default::default() - } - ); + assert_eq!(res.last_insert_id, metadata.uuid); Ok(()) } From 9bd537efe347cf3f585f673f2d01221db9cba9af Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 27 Sep 2021 18:10:45 +0800 Subject: [PATCH 04/20] Fixup --- src/executor/insert.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/executor/insert.rs b/src/executor/insert.rs index cb7e5555..aa8905be 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -100,7 +100,7 @@ where .map(|col| col.to_string()) .collect::>(); let res = conn.query_one(statement).await?.unwrap(); - Some(res.try_get_many("", cols.as_ref()).unwrap_or_default()) + res.try_get_many("", cols.as_ref()).ok() } _ => { let last_insert_id = db.execute(statement).await?.last_insert_id(); From a1a7a98a5c0a62af2521209e38e21fa867f9af30 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 28 Sep 2021 18:21:00 +0800 Subject: [PATCH 05/20] Set SqlxSqlit pool max connection to 1 --- src/driver/sqlx_sqlite.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index b02f4408..db3fa4e2 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -1,5 +1,5 @@ use sqlx::{ - sqlite::{SqliteArguments, SqliteQueryResult, SqliteRow}, + sqlite::{SqliteArguments, SqlitePoolOptions, SqliteQueryResult, SqliteRow}, Sqlite, SqlitePool, }; @@ -24,7 +24,11 @@ impl SqlxSqliteConnector { } pub async fn connect(string: &str) -> Result { - if let Ok(pool) = SqlitePool::connect(string).await { + if let Ok(pool) = SqlitePoolOptions::new() + .max_connections(1) + .connect(string) + .await + { Ok(DatabaseConnection::SqlxSqlitePoolConnection( SqlxSqlitePoolConnection { pool }, )) From 97b95bf61285d6ba7fef29e6d1d3599a54c22370 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 28 Sep 2021 18:23:42 +0800 Subject: [PATCH 06/20] cargo fmt --- src/executor/insert.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/executor/insert.rs b/src/executor/insert.rs index 630ee6a7..4a7b55a2 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -1,6 +1,6 @@ use crate::{ - error::*, ActiveModelTrait, DatabaseConnection, DbBackend, EntityTrait, Insert, PrimaryKeyTrait, - Statement, TryFromU64, + error::*, ActiveModelTrait, DatabaseConnection, DbBackend, EntityTrait, Insert, + PrimaryKeyTrait, Statement, TryFromU64, }; use sea_query::InsertStatement; use std::{future::Future, marker::PhantomData}; From 3123a9d129964058ae81a555ad83cdc6a82eab29 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Thu, 30 Sep 2021 11:40:27 +0800 Subject: [PATCH 07/20] Fix git merge conflict --- src/executor/insert.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/executor/insert.rs b/src/executor/insert.rs index 4a7b55a2..ed4da269 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -91,14 +91,13 @@ where { type PrimaryKey = <::Entity as EntityTrait>::PrimaryKey; type ValueTypeOf = as PrimaryKeyTrait>::ValueType; - let last_insert_id_opt = match db { - #[cfg(feature = "sqlx-postgres")] - DatabaseConnection::SqlxPostgresPoolConnection(conn) => { + let last_insert_id_opt = match db.get_database_backend() { + DbBackend::Postgres => { use crate::{sea_query::Iden, Iterable}; let cols = PrimaryKey::::iter() .map(|col| col.to_string()) .collect::>(); - let res = conn.query_one(statement).await?.unwrap(); + let res = db.query_one(statement).await?.unwrap(); res.try_get_many("", cols.as_ref()).ok() } _ => { From 5497810afb08b1c6bbd0ef39ac392a94ca06f52a Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Thu, 30 Sep 2021 11:49:27 +0800 Subject: [PATCH 08/20] Remove unnecessary trait bounds --- src/entity/active_model.rs | 7 +------ src/entity/base_entity.rs | 8 +++----- src/query/insert.rs | 8 -------- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index c69e5b01..ab076bf0 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -1,6 +1,5 @@ use crate::{ - error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, - PrimaryKeyValue, Value, + error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, Value, }; use async_trait::async_trait; use std::fmt::Debug; @@ -70,8 +69,6 @@ pub trait ActiveModelTrait: Clone + Debug { async fn insert(self, db: &DatabaseConnection) -> Result where ::Model: IntoActiveModel, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { let am = self; let exec = ::insert(am).exec(db); @@ -96,8 +93,6 @@ pub trait ActiveModelTrait: Clone + Debug { where Self: ActiveModelBehavior, ::Model: IntoActiveModel, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { let mut am = self; am = ActiveModelBehavior::before_save(am); diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index 79caaf0b..d691fb3e 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -49,7 +49,9 @@ pub trait EntityTrait: EntityName { type Relation: RelationTrait; - type PrimaryKey: PrimaryKeyTrait + PrimaryKeyToColumn; + type PrimaryKey: PrimaryKeyTrait + + PrimaryKeyToColumn + + PrimaryKeyValue; fn belongs_to(related: R) -> RelationBuilder where @@ -299,8 +301,6 @@ pub trait EntityTrait: EntityName { fn insert(model: A) -> Insert where A: ActiveModelTrait, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { Insert::one(model) } @@ -354,8 +354,6 @@ pub trait EntityTrait: EntityName { where A: ActiveModelTrait, I: IntoIterator, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { Insert::many(models) } diff --git a/src/query/insert.rs b/src/query/insert.rs index 418d2b70..59c06b97 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -73,8 +73,6 @@ where pub fn one(m: M) -> Insert where M: IntoActiveModel, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { Self::new().add(m) } @@ -104,8 +102,6 @@ where where M: IntoActiveModel, I: IntoIterator, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { Self::new().add_many(models) } @@ -114,8 +110,6 @@ where pub fn add(mut self, m: M) -> Self where M: IntoActiveModel, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { let mut am: A = m.into_active_model(); self.primary_key = @@ -149,8 +143,6 @@ where where M: IntoActiveModel, I: IntoIterator, - <::Entity as EntityTrait>::PrimaryKey: - PrimaryKeyValue<::Entity>, { for model in models.into_iter() { self = self.add(model); From 35b8eb9a4df9c284f03625c707c677f978b881fb Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 4 Oct 2021 12:17:31 +0800 Subject: [PATCH 09/20] `ActiveValue::take()` & `ActiveValue::into_value()` without `unwrap()` --- src/entity/active_model.rs | 12 ++++++------ src/query/insert.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index cfcb0bbd..6f4b86f6 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -209,23 +209,23 @@ where matches!(self.state, ActiveValueState::Unset) } - pub fn take(&mut self) -> V { + pub fn take(&mut self) -> Option { self.state = ActiveValueState::Unset; - self.value.take().unwrap() + self.value.take() } pub fn unwrap(self) -> V { self.value.unwrap() } - pub fn into_value(self) -> Value { - self.value.unwrap().into() + pub fn into_value(self) -> Option { + self.value.map(Into::into) } pub fn into_wrapped_value(self) -> ActiveValue { match self.state { - ActiveValueState::Set => ActiveValue::set(self.into_value()), - ActiveValueState::Unchanged => ActiveValue::unchanged(self.into_value()), + ActiveValueState::Set => ActiveValue::set(self.into_value().unwrap()), + ActiveValueState::Unchanged => ActiveValue::unchanged(self.into_value().unwrap()), ActiveValueState::Unset => ActiveValue::unset(), } } diff --git a/src/query/insert.rs b/src/query/insert.rs index a65071e1..f2d60dc8 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -120,7 +120,7 @@ where } if av_has_val { columns.push(col); - values.push(av.into_value()); + values.push(av.into_value().unwrap()); } } self.query.columns(columns); From a9f9599a4d3285ed46a08f55c1382c7f35584138 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 5 Oct 2021 23:03:04 +0800 Subject: [PATCH 10/20] Codegen date & time column Rust type mapping --- sea-orm-codegen/src/entity/column.rs | 40 +++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 532f2e91..69eb0fb6 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -27,8 +27,6 @@ impl Column { ColumnType::Char(_) | ColumnType::String(_) | ColumnType::Text - | ColumnType::Time(_) - | ColumnType::Date | ColumnType::Custom(_) => "String", ColumnType::TinyInteger(_) => "i8", ColumnType::SmallInteger(_) => "i16", @@ -37,6 +35,8 @@ impl Column { ColumnType::Float(_) => "f32", ColumnType::Double(_) => "f64", ColumnType::Json | ColumnType::JsonBinary => "Json", + ColumnType::Date => "Date", + ColumnType::Time(_) => "Time", ColumnType::DateTime(_) | ColumnType::Timestamp(_) => "DateTime", ColumnType::TimestampWithTimeZone(_) => "DateTimeWithTimeZone", ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal", @@ -194,6 +194,11 @@ mod tests { make_col!("CAKE_FILLING_ID", ColumnType::Double(None)), make_col!("CAKE-FILLING-ID", ColumnType::Binary(None)), make_col!("CAKE", ColumnType::Boolean), + make_col!("date", ColumnType::Date), + make_col!("time", ColumnType::Time(None)), + make_col!("date_time", ColumnType::DateTime(None)), + make_col!("timestamp", ColumnType::Timestamp(None)), + make_col!("timestamp_tz", ColumnType::TimestampWithTimeZone(None)), ] } @@ -211,6 +216,11 @@ mod tests { "cake_filling_id", "cake_filling_id", "cake", + "date", + "time", + "date_time", + "timestamp", + "timestamp_tz", ]; for (col, snack_case) in columns.into_iter().zip(snack_cases) { assert_eq!(col.get_name_snake_case().to_string(), snack_case); @@ -231,6 +241,11 @@ mod tests { "CakeFillingId", "CakeFillingId", "Cake", + "Date", + "Time", + "DateTime", + "Timestamp", + "TimestampTz", ]; for (col, camel_case) in columns.into_iter().zip(camel_cases) { assert_eq!(col.get_name_camel_case().to_string(), camel_case); @@ -241,7 +256,21 @@ mod tests { fn test_get_rs_type() { let columns = setup(); let rs_types = vec![ - "String", "String", "i8", "i16", "i32", "i64", "f32", "f64", "Vec", "bool", + "String", + "String", + "i8", + "i16", + "i32", + "i64", + "f32", + "f64", + "Vec", + "bool", + "Date", + "Time", + "DateTime", + "DateTime", + "DateTimeWithTimeZone", ]; for (mut col, rs_type) in columns.into_iter().zip(rs_types) { let rs_type: TokenStream = rs_type.parse().unwrap(); @@ -271,6 +300,11 @@ mod tests { "ColumnType::Double.def()", "ColumnType::Binary.def()", "ColumnType::Boolean.def()", + "ColumnType::Date.def()", + "ColumnType::Time.def()", + "ColumnType::DateTime.def()", + "ColumnType::Timestamp.def()", + "ColumnType::TimestampWithTimeZone.def()", ]; for (mut col, col_def) in columns.into_iter().zip(col_defs) { let mut col_def: TokenStream = col_def.parse().unwrap(); From cab0f6ba6e5ef5421aa8f15e109fd93898d7336c Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Thu, 7 Oct 2021 16:35:50 +0800 Subject: [PATCH 11/20] Merge pull request #224 from SeaQL/rust-keywords Escape rust keywords with `r#` raw identifier --- sea-orm-codegen/src/entity/column.rs | 5 +- sea-orm-codegen/src/entity/writer.rs | 72 ++++++++- sea-orm-codegen/src/lib.rs | 1 + sea-orm-codegen/src/util.rs | 23 +++ sea-orm-codegen/tests/compact/rust_keyword.rs | 30 ++++ .../tests/expanded/rust_keyword.rs | 79 ++++++++++ sea-orm-macros/src/derives/active_model.rs | 10 +- sea-orm-macros/src/derives/entity_model.rs | 12 +- sea-orm-macros/src/derives/model.rs | 13 +- sea-orm-macros/src/util.rs | 36 +++++ src/tests_cfg/mod.rs | 2 + src/tests_cfg/rust_keyword.rs | 141 ++++++++++++++++++ 12 files changed, 406 insertions(+), 18 deletions(-) create mode 100644 sea-orm-codegen/src/util.rs create mode 100644 sea-orm-codegen/tests/compact/rust_keyword.rs create mode 100644 sea-orm-codegen/tests/expanded/rust_keyword.rs create mode 100644 src/tests_cfg/rust_keyword.rs diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 69eb0fb6..39eb340c 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -1,3 +1,4 @@ +use crate::util::escape_rust_keyword; use heck::{CamelCase, SnakeCase}; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; @@ -14,11 +15,11 @@ pub struct Column { impl Column { pub fn get_name_snake_case(&self) -> Ident { - format_ident!("{}", self.name.to_snake_case()) + format_ident!("{}", escape_rust_keyword(self.name.to_snake_case())) } pub fn get_name_camel_case(&self) -> Ident { - format_ident!("{}", self.name.to_camel_case()) + format_ident!("{}", escape_rust_keyword(self.name.to_camel_case())) } pub fn get_rs_type(&self) -> TokenStream { diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 59f54537..17e74130 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -597,18 +597,85 @@ mod tests { name: "id".to_owned(), }], }, + Entity { + table_name: "rust_keyword".to_owned(), + columns: vec![ + Column { + name: "id".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: true, + not_null: true, + unique: false, + }, + Column { + name: "testing".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "rust".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "keywords".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "type".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "typeof".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "crate".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + Column { + name: "self".to_owned(), + col_type: ColumnType::Integer(Some(11)), + auto_increment: false, + not_null: true, + unique: false, + }, + ], + relations: vec![], + conjunct_relations: vec![], + primary_keys: vec![PrimaryKey { + name: "id".to_owned(), + }], + }, ] } #[test] fn test_gen_expanded_code_blocks() -> io::Result<()> { let entities = setup(); - const ENTITY_FILES: [&str; 5] = [ + const ENTITY_FILES: [&str; 6] = [ include_str!("../../tests/expanded/cake.rs"), include_str!("../../tests/expanded/cake_filling.rs"), include_str!("../../tests/expanded/filling.rs"), include_str!("../../tests/expanded/fruit.rs"), include_str!("../../tests/expanded/vendor.rs"), + include_str!("../../tests/expanded/rust_keyword.rs"), ]; assert_eq!(entities.len(), ENTITY_FILES.len()); @@ -642,12 +709,13 @@ mod tests { #[test] fn test_gen_compact_code_blocks() -> io::Result<()> { let entities = setup(); - const ENTITY_FILES: [&str; 5] = [ + const ENTITY_FILES: [&str; 6] = [ include_str!("../../tests/compact/cake.rs"), include_str!("../../tests/compact/cake_filling.rs"), include_str!("../../tests/compact/filling.rs"), include_str!("../../tests/compact/fruit.rs"), include_str!("../../tests/compact/vendor.rs"), + include_str!("../../tests/compact/rust_keyword.rs"), ]; assert_eq!(entities.len(), ENTITY_FILES.len()); diff --git a/sea-orm-codegen/src/lib.rs b/sea-orm-codegen/src/lib.rs index 07e167bc..5e637de1 100644 --- a/sea-orm-codegen/src/lib.rs +++ b/sea-orm-codegen/src/lib.rs @@ -1,5 +1,6 @@ mod entity; mod error; +mod util; pub use entity::*; pub use error::*; diff --git a/sea-orm-codegen/src/util.rs b/sea-orm-codegen/src/util.rs new file mode 100644 index 00000000..34c46c54 --- /dev/null +++ b/sea-orm-codegen/src/util.rs @@ -0,0 +1,23 @@ +pub(crate) fn escape_rust_keyword(string: T) -> String +where + T: ToString, +{ + let string = string.to_string(); + if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("r#{}", string) + } else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("{}_", string) + } else { + string + } +} + +pub(crate) const RUST_KEYWORDS: [&str; 49] = [ + "as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false", + "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", + "return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use", + "where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv", + "try", "typeof", "unsized", "virtual", "yield", +]; + +pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"]; diff --git a/sea-orm-codegen/tests/compact/rust_keyword.rs b/sea-orm-codegen/tests/compact/rust_keyword.rs new file mode 100644 index 00000000..229eae22 --- /dev/null +++ b/sea-orm-codegen/tests/compact/rust_keyword.rs @@ -0,0 +1,30 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "rust_keyword")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#type: i32, + pub r#typeof: i32, + pub crate_: i32, + pub self_: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + _ => panic!("No RelationDef"), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded/rust_keyword.rs b/sea-orm-codegen/tests/expanded/rust_keyword.rs new file mode 100644 index 00000000..1ab8a627 --- /dev/null +++ b/sea-orm-codegen/tests/expanded/rust_keyword.rs @@ -0,0 +1,79 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "rust_keyword" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#type: i32, + pub r#typeof: i32, + pub crate_: i32, + pub self_: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Testing, + Rust, + Keywords, + Type, + Typeof, + Crate, + Self_, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Testing => ColumnType::Integer.def(), + Self::Rust => ColumnType::Integer.def(), + Self::Keywords => ColumnType::Integer.def(), + Self::Type => ColumnType::Integer.def(), + Self::Typeof => ColumnType::Integer.def(), + Self::Crate => ColumnType::Integer.def(), + Self::Self_ => ColumnType::Integer.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + _ => panic!("No RelationDef"), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 2227f09b..85bdcb69 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -1,4 +1,4 @@ -use crate::util::field_not_ignored; +use crate::util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier}; use heck::CamelCase; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, quote_spanned}; @@ -29,10 +29,10 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result) -> syn::Result { // if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct let mut table_name = None; @@ -60,8 +60,10 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res if let Fields::Named(fields) = item_struct.fields { for field in fields.named { if let Some(ident) = &field.ident { - let mut field_name = - Ident::new(&ident.to_string().to_case(Case::Pascal), Span::call_site()); + let mut field_name = Ident::new( + &trim_starting_raw_identifier(&ident).to_case(Case::Pascal), + Span::call_site(), + ); let mut nullable = false; let mut default_value = None; @@ -168,6 +170,8 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res field_name = enum_name; } + field_name = Ident::new(&escape_rust_keyword(field_name), Span::call_site()); + if ignore { continue; } else { diff --git a/sea-orm-macros/src/derives/model.rs b/sea-orm-macros/src/derives/model.rs index a43b487f..29a597b9 100644 --- a/sea-orm-macros/src/derives/model.rs +++ b/sea-orm-macros/src/derives/model.rs @@ -1,4 +1,7 @@ -use crate::{attributes::derive_attr, util::field_not_ignored}; +use crate::{ + attributes::derive_attr, + util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier}, +}; use heck::CamelCase; use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; @@ -43,10 +46,10 @@ impl DeriveModel { let column_idents = fields .iter() .map(|field| { - let mut ident = format_ident!( - "{}", - field.ident.as_ref().unwrap().to_string().to_camel_case() - ); + let ident = field.ident.as_ref().unwrap().to_string(); + let ident = trim_starting_raw_identifier(ident).to_camel_case(); + let ident = escape_rust_keyword(ident); + let mut ident = format_ident!("{}", &ident); for attr in field.attrs.iter() { if let Some(ident) = attr.path.get_ident() { if ident != "sea_orm" { diff --git a/sea-orm-macros/src/util.rs b/sea-orm-macros/src/util.rs index 7dda1087..379b486c 100644 --- a/sea-orm-macros/src/util.rs +++ b/sea-orm-macros/src/util.rs @@ -24,3 +24,39 @@ pub(crate) fn field_not_ignored(field: &Field) -> bool { } true } + +pub(crate) fn trim_starting_raw_identifier(string: T) -> String +where + T: ToString, +{ + string + .to_string() + .trim_start_matches(RAW_IDENTIFIER) + .to_string() +} + +pub(crate) fn escape_rust_keyword(string: T) -> String +where + T: ToString, +{ + let string = string.to_string(); + if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("r#{}", string) + } else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) { + format!("{}_", string) + } else { + string + } +} + +pub(crate) const RAW_IDENTIFIER: &str = "r#"; + +pub(crate) const RUST_KEYWORDS: [&str; 49] = [ + "as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false", + "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", + "return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use", + "where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv", + "try", "typeof", "unsized", "virtual", "yield", +]; + +pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"]; diff --git a/src/tests_cfg/mod.rs b/src/tests_cfg/mod.rs index 6bc86aed..d6c80b36 100644 --- a/src/tests_cfg/mod.rs +++ b/src/tests_cfg/mod.rs @@ -7,6 +7,7 @@ pub mod cake_filling_price; pub mod entity_linked; pub mod filling; pub mod fruit; +pub mod rust_keyword; pub mod vendor; pub use cake::Entity as Cake; @@ -15,4 +16,5 @@ pub use cake_filling::Entity as CakeFilling; pub use cake_filling_price::Entity as CakeFillingPrice; pub use filling::Entity as Filling; pub use fruit::Entity as Fruit; +pub use rust_keyword::Entity as RustKeyword; pub use vendor::Entity as Vendor; diff --git a/src/tests_cfg/rust_keyword.rs b/src/tests_cfg/rust_keyword.rs new file mode 100644 index 00000000..c8662347 --- /dev/null +++ b/src/tests_cfg/rust_keyword.rs @@ -0,0 +1,141 @@ +use crate as sea_orm; +use crate::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "rust_keyword")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub testing: i32, + pub rust: i32, + pub keywords: i32, + pub r#raw_identifier: i32, + pub r#as: i32, + pub r#async: i32, + pub r#await: i32, + pub r#break: i32, + pub r#const: i32, + pub r#continue: i32, + pub crate_: i32, + pub r#dyn: i32, + pub r#else: i32, + pub r#enum: i32, + pub r#extern: i32, + pub r#false: i32, + pub r#fn: i32, + pub r#for: i32, + pub r#if: i32, + pub r#impl: i32, + pub r#in: i32, + pub r#let: i32, + pub r#loop: i32, + pub r#match: i32, + pub r#mod: i32, + pub r#move: i32, + pub r#mut: i32, + pub r#pub: i32, + pub r#ref: i32, + pub r#return: i32, + pub self_: i32, + pub r#static: i32, + pub r#struct: i32, + pub r#trait: i32, + pub r#true: i32, + pub r#type: i32, + pub r#union: i32, + pub r#unsafe: i32, + pub r#use: i32, + pub r#where: i32, + pub r#while: i32, + pub r#abstract: i32, + pub r#become: i32, + pub r#box: i32, + pub r#do: i32, + pub r#final: i32, + pub r#macro: i32, + pub r#override: i32, + pub r#priv: i32, + pub r#try: i32, + pub r#typeof: i32, + pub r#unsized: i32, + pub r#virtual: i32, + pub r#yield: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + _ => panic!("No RelationDef"), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} + +#[cfg(test)] +mod tests { + use crate::tests_cfg::rust_keyword::*; + use sea_query::Iden; + + #[test] + fn test_columns() { + assert_eq!(Column::Id.to_string().as_str(), "id"); + assert_eq!(Column::Testing.to_string().as_str(), "testing"); + assert_eq!(Column::Rust.to_string().as_str(), "rust"); + assert_eq!(Column::Keywords.to_string().as_str(), "keywords"); + assert_eq!(Column::RawIdentifier.to_string().as_str(), "raw_identifier"); + assert_eq!(Column::As.to_string().as_str(), "as"); + assert_eq!(Column::Async.to_string().as_str(), "async"); + assert_eq!(Column::Await.to_string().as_str(), "await"); + assert_eq!(Column::Break.to_string().as_str(), "break"); + assert_eq!(Column::Const.to_string().as_str(), "const"); + assert_eq!(Column::Continue.to_string().as_str(), "continue"); + assert_eq!(Column::Dyn.to_string().as_str(), "dyn"); + assert_eq!(Column::Crate.to_string().as_str(), "crate"); + assert_eq!(Column::Else.to_string().as_str(), "else"); + assert_eq!(Column::Enum.to_string().as_str(), "enum"); + assert_eq!(Column::Extern.to_string().as_str(), "extern"); + assert_eq!(Column::False.to_string().as_str(), "false"); + assert_eq!(Column::Fn.to_string().as_str(), "fn"); + assert_eq!(Column::For.to_string().as_str(), "for"); + assert_eq!(Column::If.to_string().as_str(), "if"); + assert_eq!(Column::Impl.to_string().as_str(), "impl"); + assert_eq!(Column::In.to_string().as_str(), "in"); + assert_eq!(Column::Let.to_string().as_str(), "let"); + assert_eq!(Column::Loop.to_string().as_str(), "loop"); + assert_eq!(Column::Match.to_string().as_str(), "match"); + assert_eq!(Column::Mod.to_string().as_str(), "mod"); + assert_eq!(Column::Move.to_string().as_str(), "move"); + assert_eq!(Column::Mut.to_string().as_str(), "mut"); + assert_eq!(Column::Pub.to_string().as_str(), "pub"); + assert_eq!(Column::Ref.to_string().as_str(), "ref"); + assert_eq!(Column::Return.to_string().as_str(), "return"); + assert_eq!(Column::Self_.to_string().as_str(), "self"); + assert_eq!(Column::Static.to_string().as_str(), "static"); + assert_eq!(Column::Struct.to_string().as_str(), "struct"); + assert_eq!(Column::Trait.to_string().as_str(), "trait"); + assert_eq!(Column::True.to_string().as_str(), "true"); + assert_eq!(Column::Type.to_string().as_str(), "type"); + assert_eq!(Column::Union.to_string().as_str(), "union"); + assert_eq!(Column::Unsafe.to_string().as_str(), "unsafe"); + assert_eq!(Column::Use.to_string().as_str(), "use"); + assert_eq!(Column::Where.to_string().as_str(), "where"); + assert_eq!(Column::While.to_string().as_str(), "while"); + assert_eq!(Column::Abstract.to_string().as_str(), "abstract"); + assert_eq!(Column::Become.to_string().as_str(), "become"); + assert_eq!(Column::Box.to_string().as_str(), "box"); + assert_eq!(Column::Do.to_string().as_str(), "do"); + assert_eq!(Column::Final.to_string().as_str(), "final"); + assert_eq!(Column::Macro.to_string().as_str(), "macro"); + assert_eq!(Column::Override.to_string().as_str(), "override"); + assert_eq!(Column::Priv.to_string().as_str(), "priv"); + assert_eq!(Column::Try.to_string().as_str(), "try"); + assert_eq!(Column::Typeof.to_string().as_str(), "typeof"); + assert_eq!(Column::Unsized.to_string().as_str(), "unsized"); + assert_eq!(Column::Virtual.to_string().as_str(), "virtual"); + assert_eq!(Column::Yield.to_string().as_str(), "yield"); + } +} From 2f90207d643f6cbc14a3f3b848a497f584627317 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 8 Oct 2021 18:04:42 +0800 Subject: [PATCH 12/20] Remove `PrimaryKeyValue` trait --- Cargo.toml | 2 +- sea-orm-macros/src/derives/primary_key.rs | 30 ++--------------- src/entity/active_model.rs | 39 ++++++++++++++++++++++- src/entity/base_entity.rs | 8 ++--- src/entity/prelude.rs | 4 +-- src/entity/primary_key.rs | 22 ++++++------- src/executor/insert.rs | 15 +++------ src/query/insert.rs | 8 ++--- 8 files changed, 65 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a8d7a8ca..8b813343 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.2.5", path = "sea-orm-macros", optional = true } -sea-query = { version = "^0.17.0", features = ["thread-safe"] } +sea-query = { version = "^0.17.0", git = "https://github.com/SeaQL/sea-query.git", branch = "from-value-tuple", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1", optional = true } diff --git a/sea-orm-macros/src/derives/primary_key.rs b/sea-orm-macros/src/derives/primary_key.rs index ce7ca840..e677e2e6 100644 --- a/sea-orm-macros/src/derives/primary_key.rs +++ b/sea-orm-macros/src/derives/primary_key.rs @@ -1,7 +1,7 @@ use heck::SnakeCase; use proc_macro2::{Ident, TokenStream}; -use quote::{quote, quote_spanned, ToTokens}; -use syn::{punctuated::Punctuated, token::Comma, Data, DataEnum, Fields, Variant}; +use quote::{quote, quote_spanned}; +use syn::{Data, DataEnum, Fields, Variant}; pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result { let variants = match data { @@ -30,21 +30,6 @@ pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result = - variants.iter().fold(Punctuated::new(), |mut acc, v| { - let variant = &v.ident; - acc.push( - quote! { active_model.take(#ident::#variant.into_column()).unwrap().unwrap() }, - ); - acc - }); - let mut primary_key_value = primary_key_value.to_token_stream(); - if variants.len() > 1 { - primary_key_value = quote! { - (#primary_key_value) - }; - } - Ok(quote!( impl sea_orm::Iden for #ident { fn unquoted(&self, s: &mut dyn std::fmt::Write) { @@ -76,16 +61,5 @@ pub fn expand_derive_primary_key(ident: Ident, data: Data) -> syn::Result for #ident { - fn get_primary_key_value( - mut active_model: A, - ) -> <::PrimaryKey as PrimaryKeyTrait>::ValueType - where - A: ActiveModelTrait, - { - #primary_key_value - } - } )) } diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index ab076bf0..0243cc7d 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -2,6 +2,7 @@ use crate::{ error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, Value, }; use async_trait::async_trait; +use sea_query::ValueTuple; use std::fmt::Debug; #[derive(Clone, Debug, Default)] @@ -9,7 +10,8 @@ pub struct ActiveValue where V: Into, { - value: Option, + // Don't want to call ActiveValue::unwrap() and cause panic + pub(self) value: Option, state: ActiveValueState, } @@ -66,6 +68,41 @@ pub trait ActiveModelTrait: Clone + Debug { fn default() -> Self; + fn get_primary_key_value(&self) -> Option { + let mut cols = ::PrimaryKey::iter(); + macro_rules! next { + () => { + if let Some(col) = cols.next() { + if let Some(val) = self.get(col.into_column()).value { + val + } else { + return None; + } + } else { + return None; + } + }; + } + match ::PrimaryKey::iter().count() { + 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)) + } + _ => panic!("The arity cannot be larger than 3"), + } + } + async fn insert(self, db: &DatabaseConnection) -> Result where ::Model: IntoActiveModel, diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index d691fb3e..764f2524 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -1,7 +1,7 @@ use crate::{ ActiveModelTrait, ColumnTrait, Delete, DeleteMany, DeleteOne, FromQueryResult, Insert, - ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, Related, - RelationBuilder, RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne, + ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, Related, RelationBuilder, + RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne, }; use sea_query::{Alias, Iden, IntoIden, IntoTableRef, IntoValueTuple, TableRef}; pub use sea_strum::IntoEnumIterator as Iterable; @@ -49,9 +49,7 @@ pub trait EntityTrait: EntityName { type Relation: RelationTrait; - type PrimaryKey: PrimaryKeyTrait - + PrimaryKeyToColumn - + PrimaryKeyValue; + type PrimaryKey: PrimaryKeyTrait + PrimaryKeyToColumn; fn belongs_to(related: R) -> RelationBuilder where diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs index 1fecfa96..fd61613b 100644 --- a/src/entity/prelude.rs +++ b/src/entity/prelude.rs @@ -1,8 +1,8 @@ pub use crate::{ error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType, EntityName, EntityTrait, EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, ModelTrait, - PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, QueryResult, Related, - RelationDef, RelationTrait, Select, Value, + PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef, + RelationTrait, Select, Value, }; #[cfg(feature = "macros")] diff --git a/src/entity/primary_key.rs b/src/entity/primary_key.rs index 530eba30..a5e4cde0 100644 --- a/src/entity/primary_key.rs +++ b/src/entity/primary_key.rs @@ -1,11 +1,18 @@ use super::{ColumnTrait, IdenStatic, Iterable}; -use crate::{ActiveModelTrait, EntityTrait, TryFromU64, TryGetableMany}; -use sea_query::IntoValueTuple; +use crate::{TryFromU64, TryGetableMany}; +use sea_query::{FromValueTuple, IntoValueTuple}; use std::fmt::Debug; //LINT: composite primary key cannot auto increment pub trait PrimaryKeyTrait: IdenStatic + Iterable { - type ValueType: Sized + Send + Debug + PartialEq + IntoValueTuple + TryGetableMany + TryFromU64; + type ValueType: Sized + + Send + + Debug + + PartialEq + + IntoValueTuple + + FromValueTuple + + TryGetableMany + + TryFromU64; fn auto_increment() -> bool; } @@ -19,12 +26,3 @@ pub trait PrimaryKeyToColumn { where Self: Sized; } - -pub trait PrimaryKeyValue -where - E: EntityTrait, -{ - fn get_primary_key_value(active_model: A) -> ::ValueType - where - A: ActiveModelTrait; -} diff --git a/src/executor/insert.rs b/src/executor/insert.rs index ed4da269..02d02c0b 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -2,7 +2,7 @@ use crate::{ error::*, ActiveModelTrait, DatabaseConnection, DbBackend, EntityTrait, Insert, PrimaryKeyTrait, Statement, TryFromU64, }; -use sea_query::InsertStatement; +use sea_query::{FromValueTuple, InsertStatement, ValueTuple}; use std::{future::Future, marker::PhantomData}; #[derive(Debug)] @@ -10,7 +10,7 @@ pub struct Inserter where A: ActiveModelTrait, { - primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, + primary_key: Option, query: InsertStatement, model: PhantomData, } @@ -35,7 +35,6 @@ where where A: 'a, { - // TODO: extract primary key's value from query // so that self is dropped before entering await let mut query = self.query; if db.get_database_backend() == DbBackend::Postgres { @@ -49,7 +48,6 @@ where } } Inserter::::new(self.primary_key, query).exec(db) - // TODO: return primary key if extracted before, otherwise use InsertResult } } @@ -57,10 +55,7 @@ impl Inserter where A: ActiveModelTrait, { - pub fn new( - primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, - query: InsertStatement, - ) -> Self { + pub fn new(primary_key: Option, query: InsertStatement) -> Self { Self { primary_key, query, @@ -82,7 +77,7 @@ where // Only Statement impl Send async fn exec_insert( - primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, + primary_key: Option, statement: Statement, db: &DatabaseConnection, ) -> Result, DbErr> @@ -108,7 +103,7 @@ where let last_insert_id = match last_insert_id_opt { Some(last_insert_id) => last_insert_id, None => match primary_key { - Some(primary_key) => primary_key, + Some(value_tuple) => FromValueTuple::from_value_tuple(value_tuple), None => return Err(DbErr::Exec("Fail to unpack last_insert_id".to_owned())), }, }; diff --git a/src/query/insert.rs b/src/query/insert.rs index 59c06b97..615ce06e 100644 --- a/src/query/insert.rs +++ b/src/query/insert.rs @@ -1,9 +1,9 @@ use crate::{ ActiveModelTrait, EntityName, EntityTrait, IntoActiveModel, Iterable, PrimaryKeyTrait, - PrimaryKeyValue, QueryTrait, + QueryTrait, }; use core::marker::PhantomData; -use sea_query::InsertStatement; +use sea_query::{InsertStatement, ValueTuple}; #[derive(Debug)] pub struct Insert @@ -12,7 +12,7 @@ where { pub(crate) query: InsertStatement, pub(crate) columns: Vec, - pub(crate) primary_key: Option<<<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>, + pub(crate) primary_key: Option, pub(crate) model: PhantomData, } @@ -114,7 +114,7 @@ where let mut am: A = m.into_active_model(); self.primary_key = if !<::PrimaryKey as PrimaryKeyTrait>::auto_increment() { - Some(<::PrimaryKey as PrimaryKeyValue>::get_primary_key_value::(am.clone())) + am.get_primary_key_value() } else { None }; From 23215c8dd53000b3d7eca75be1bf842ab7d1842a Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 8 Oct 2021 18:22:25 +0800 Subject: [PATCH 13/20] fix clippy warnings --- src/entity/active_model.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 0243cc7d..5b4289f9 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -68,6 +68,7 @@ pub trait ActiveModelTrait: Clone + Debug { fn default() -> Self; + #[allow(clippy::question_mark)] fn get_primary_key_value(&self) -> Option { let mut cols = ::PrimaryKey::iter(); macro_rules! next { From c24d7704d9ae76485ec9312373284982510e140e Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 14:38:09 +0800 Subject: [PATCH 14/20] Move examples #232 --- .github/workflows/rust.yml | 24 ++++++++++++++++++- examples/{async-std => basic}/Cargo.toml | 0 examples/{async-std => basic}/Readme.md | 0 examples/{async-std => basic}/bakery.sql | 0 examples/{async-std => basic}/import.sh | 0 examples/{async-std => basic}/src/entities.rs | 0 .../{async-std => basic}/src/example_cake.rs | 0 .../src/example_cake_filling.rs | 0 .../src/example_filling.rs | 0 .../{async-std => basic}/src/example_fruit.rs | 0 examples/{async-std => basic}/src/main.rs | 0 .../{async-std => basic}/src/operation.rs | 0 examples/{async-std => basic}/src/select.rs | 0 {examples/tokio => issues/86}/Cargo.toml | 0 {examples/tokio => issues/86}/src/cake.rs | 0 {examples/tokio => issues/86}/src/main.rs | 0 16 files changed, 23 insertions(+), 1 deletion(-) rename examples/{async-std => basic}/Cargo.toml (100%) rename examples/{async-std => basic}/Readme.md (100%) rename examples/{async-std => basic}/bakery.sql (100%) rename examples/{async-std => basic}/import.sh (100%) rename examples/{async-std => basic}/src/entities.rs (100%) rename examples/{async-std => basic}/src/example_cake.rs (100%) rename examples/{async-std => basic}/src/example_cake_filling.rs (100%) rename examples/{async-std => basic}/src/example_filling.rs (100%) rename examples/{async-std => basic}/src/example_fruit.rs (100%) rename examples/{async-std => basic}/src/main.rs (100%) rename examples/{async-std => basic}/src/operation.rs (100%) rename examples/{async-std => basic}/src/select.rs (100%) rename {examples/tokio => issues/86}/Cargo.toml (100%) rename {examples/tokio => issues/86}/src/cake.rs (100%) rename {examples/tokio => issues/86}/src/main.rs (100%) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5a5e6e91..ec5ea734 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -171,7 +171,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - path: [async-std, tokio, actix_example, actix4_example, rocket_example] + path: [basic, actix_example, actix4_example, rocket_example] steps: - uses: actions/checkout@v2 @@ -187,6 +187,28 @@ jobs: args: > --manifest-path examples/${{ matrix.path }}/Cargo.toml + issues: + name: Issues + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + path: [86] + steps: + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - uses: actions-rs/cargo@v1 + with: + command: build + args: > + --manifest-path issues/${{ matrix.path }}/Cargo.toml + sqlite: name: SQLite runs-on: ubuntu-20.04 diff --git a/examples/async-std/Cargo.toml b/examples/basic/Cargo.toml similarity index 100% rename from examples/async-std/Cargo.toml rename to examples/basic/Cargo.toml diff --git a/examples/async-std/Readme.md b/examples/basic/Readme.md similarity index 100% rename from examples/async-std/Readme.md rename to examples/basic/Readme.md diff --git a/examples/async-std/bakery.sql b/examples/basic/bakery.sql similarity index 100% rename from examples/async-std/bakery.sql rename to examples/basic/bakery.sql diff --git a/examples/async-std/import.sh b/examples/basic/import.sh similarity index 100% rename from examples/async-std/import.sh rename to examples/basic/import.sh diff --git a/examples/async-std/src/entities.rs b/examples/basic/src/entities.rs similarity index 100% rename from examples/async-std/src/entities.rs rename to examples/basic/src/entities.rs diff --git a/examples/async-std/src/example_cake.rs b/examples/basic/src/example_cake.rs similarity index 100% rename from examples/async-std/src/example_cake.rs rename to examples/basic/src/example_cake.rs diff --git a/examples/async-std/src/example_cake_filling.rs b/examples/basic/src/example_cake_filling.rs similarity index 100% rename from examples/async-std/src/example_cake_filling.rs rename to examples/basic/src/example_cake_filling.rs diff --git a/examples/async-std/src/example_filling.rs b/examples/basic/src/example_filling.rs similarity index 100% rename from examples/async-std/src/example_filling.rs rename to examples/basic/src/example_filling.rs diff --git a/examples/async-std/src/example_fruit.rs b/examples/basic/src/example_fruit.rs similarity index 100% rename from examples/async-std/src/example_fruit.rs rename to examples/basic/src/example_fruit.rs diff --git a/examples/async-std/src/main.rs b/examples/basic/src/main.rs similarity index 100% rename from examples/async-std/src/main.rs rename to examples/basic/src/main.rs diff --git a/examples/async-std/src/operation.rs b/examples/basic/src/operation.rs similarity index 100% rename from examples/async-std/src/operation.rs rename to examples/basic/src/operation.rs diff --git a/examples/async-std/src/select.rs b/examples/basic/src/select.rs similarity index 100% rename from examples/async-std/src/select.rs rename to examples/basic/src/select.rs diff --git a/examples/tokio/Cargo.toml b/issues/86/Cargo.toml similarity index 100% rename from examples/tokio/Cargo.toml rename to issues/86/Cargo.toml diff --git a/examples/tokio/src/cake.rs b/issues/86/src/cake.rs similarity index 100% rename from examples/tokio/src/cake.rs rename to issues/86/src/cake.rs diff --git a/examples/tokio/src/main.rs b/issues/86/src/main.rs similarity index 100% rename from examples/tokio/src/main.rs rename to issues/86/src/main.rs From 12a8e5c8e90a0d503844d2b658cf42e72a32328c Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 14:40:12 +0800 Subject: [PATCH 15/20] Readme --- README.md | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b4525b31..d6bfcdff 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ SeaORM is a relational ORM to help you build light weight and concurrent web services in Rust. [![Getting Started](https://img.shields.io/badge/Getting%20Started-brightgreen)](https://www.sea-ql.org/SeaORM/docs/index) -[![Usage Example](https://img.shields.io/badge/Usage%20Example-yellow)](https://github.com/SeaQL/sea-orm/tree/master/examples/async-std) +[![Usage Example](https://img.shields.io/badge/Usage%20Example-yellow)](https://github.com/SeaQL/sea-orm/tree/master/examples/basic) [![Actix Example](https://img.shields.io/badge/Actix%20Example-blue)](https://github.com/SeaQL/sea-orm/tree/master/examples/actix_example) [![Rocket Example](https://img.shields.io/badge/Rocket%20Example-orange)](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example) [![Discord](https://img.shields.io/discord/873880840487206962?label=Discord)](https://discord.com/invite/uCPdDXzbdv) diff --git a/src/lib.rs b/src/lib.rs index 6ddc442c..1b78cf58 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ //! SeaORM is a relational ORM to help you build light weight and concurrent web services in Rust. //! //! [![Getting Started](https://img.shields.io/badge/Getting%20Started-brightgreen)](https://www.sea-ql.org/SeaORM/docs/index) -//! [![Usage Example](https://img.shields.io/badge/Usage%20Example-yellow)](https://github.com/SeaQL/sea-orm/tree/master/examples/async-std) +//! [![Usage Example](https://img.shields.io/badge/Usage%20Example-yellow)](https://github.com/SeaQL/sea-orm/tree/master/examples/basic) //! [![Actix Example](https://img.shields.io/badge/Actix%20Example-blue)](https://github.com/SeaQL/sea-orm/tree/master/examples/actix_example) //! [![Rocket Example](https://img.shields.io/badge/Rocket%20Example-orange)](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example) //! [![Discord](https://img.shields.io/discord/873880840487206962?label=Discord)](https://discord.com/invite/uCPdDXzbdv) From 7c8e766e8b34022a6e97b5953dcb4bcfbdc4390b Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 23:01:06 +0800 Subject: [PATCH 16/20] sea-orm-codegen 0.2.6 --- sea-orm-codegen/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sea-orm-codegen/Cargo.toml b/sea-orm-codegen/Cargo.toml index 0e8fa624..9013cea4 100644 --- a/sea-orm-codegen/Cargo.toml +++ b/sea-orm-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sea-orm-codegen" -version = "0.2.5" +version = "0.2.6" authors = ["Billy Chan "] edition = "2018" description = "Code Generator for SeaORM" From 0eee2206ba14b4a6d4db1a4ac9fec956046e81bc Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 23:01:46 +0800 Subject: [PATCH 17/20] sea-orm-cli 0.2.6 --- sea-orm-cli/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 3c05d08b..07db2e4b 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-orm-cli" -version = "0.2.5" +version = "0.2.6" authors = [ "Billy Chan " ] edition = "2018" description = "Command line utility for SeaORM" @@ -21,7 +21,7 @@ path = "src/main.rs" clap = { version = "^2.33.3" } dotenv = { version = "^0.15" } async-std = { version = "^1.9", features = [ "attributes" ] } -sea-orm-codegen = { version = "^0.2.5", path = "../sea-orm-codegen" } +sea-orm-codegen = { version = "^0.2.6", path = "../sea-orm-codegen" } sea-schema = { version = "^0.2.9", default-features = false, features = [ "debug-print", "sqlx-mysql", From f0aea3bf105dfe1cbeb91c2608842b8ac80720c6 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 23:15:55 +0800 Subject: [PATCH 18/20] sea-orm-macros 0.2.6 --- sea-orm-macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml index 22b58c01..cde1575c 100644 --- a/sea-orm-macros/Cargo.toml +++ b/sea-orm-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sea-orm-macros" -version = "0.2.5" +version = "0.2.6" authors = [ "Billy Chan " ] edition = "2018" description = "Derive macros for SeaORM" From bfb83044f16b55fb98f2c0634b8462c3b546ec04 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 9 Oct 2021 23:17:06 +0800 Subject: [PATCH 19/20] 0.2.6 --- CHANGELOG.md | 7 +++++++ Cargo.toml | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 693c1d0e..ee544831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 0.2.6 - 2021-10-09 + +- [[#224]] [sea-orm-cli] Date & Time column type mapping +- Escape rust keywords with `r#` raw identifier + +[#224]: https://github.com/SeaQL/sea-orm/pull/224 + ## 0.2.5 - 2021-10-06 - [[#227]] Resolve "Inserting actual none value of Option results in panic" diff --git a/Cargo.toml b/Cargo.toml index a8d7a8ca..0c8de3ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "sea-orm-macros", "sea-orm-codegen"] [package] name = "sea-orm" -version = "0.2.5" +version = "0.2.6" authors = ["Chris Tsang "] edition = "2018" description = "🐚 An async & dynamic ORM for Rust" @@ -29,7 +29,7 @@ futures = { version = "^0.3" } futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } -sea-orm-macros = { version = "^0.2.5", path = "sea-orm-macros", optional = true } +sea-orm-macros = { version = "^0.2.6", path = "sea-orm-macros", optional = true } sea-query = { version = "^0.17.0", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } From 92795a022adf3c94e42275f1387ce3dc3076ef22 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Tue, 12 Oct 2021 13:58:26 +0800 Subject: [PATCH 20/20] Bump SeaQuery --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8b813343..588658e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ futures-util = { version = "^0.3" } log = { version = "^0.4", optional = true } rust_decimal = { version = "^1", optional = true } sea-orm-macros = { version = "^0.2.5", path = "sea-orm-macros", optional = true } -sea-query = { version = "^0.17.0", git = "https://github.com/SeaQL/sea-query.git", branch = "from-value-tuple", features = ["thread-safe"] } +sea-query = { version = "^0.17.1", features = ["thread-safe"] } sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1", optional = true }