From 2f90207d643f6cbc14a3f3b848a497f584627317 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 8 Oct 2021 18:04:42 +0800 Subject: [PATCH] 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 };