Remove ValueType: Default

This commit is contained in:
Billy Chan 2021-09-27 18:01:38 +08:00
parent c12e0cd44e
commit f79a417150
No known key found for this signature in database
GPG Key ID: A2D690CAC7DF3CC7
6 changed files with 72 additions and 38 deletions

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, error::*, DatabaseConnection, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn,
PrimaryKeyTrait, Value, PrimaryKeyValue, Value,
}; };
use async_trait::async_trait; use async_trait::async_trait;
use std::fmt::Debug; use std::fmt::Debug;
@ -70,14 +70,12 @@ pub trait ActiveModelTrait: Clone + Debug {
async fn insert(self, db: &DatabaseConnection) -> Result<Self, DbErr> async fn insert(self, db: &DatabaseConnection) -> Result<Self, DbErr>
where where
<Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>, <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
<<Self as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<Self as ActiveModelTrait>::Entity>,
{ {
let am = self; let am = self;
let exec = <Self::Entity as EntityTrait>::insert(am).exec(db); let exec = <Self::Entity as EntityTrait>::insert(am).exec(db);
let res = exec.await?; let res = exec.await?;
// Assume valid last_insert_id is not equals to Default::default()
if res.last_insert_id
!= <<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType::default()
{
let found = <Self::Entity as EntityTrait>::find_by_id(res.last_insert_id) let found = <Self::Entity as EntityTrait>::find_by_id(res.last_insert_id)
.one(db) .one(db)
.await?; .await?;
@ -85,9 +83,6 @@ pub trait ActiveModelTrait: Clone + Debug {
Some(model) => Ok(model.into_active_model()), Some(model) => Ok(model.into_active_model()),
None => Err(DbErr::Exec("Failed to find inserted item".to_owned())), None => Err(DbErr::Exec("Failed to find inserted item".to_owned())),
} }
} else {
Ok(Self::default())
}
} }
async fn update(self, db: &DatabaseConnection) -> Result<Self, DbErr> { async fn update(self, db: &DatabaseConnection) -> Result<Self, DbErr> {
@ -101,6 +96,8 @@ pub trait ActiveModelTrait: Clone + Debug {
where where
Self: ActiveModelBehavior, Self: ActiveModelBehavior,
<Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>, <Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
<<Self as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<Self as ActiveModelTrait>::Entity>,
{ {
let mut am = self; let mut am = self;
am = ActiveModelBehavior::before_save(am); am = ActiveModelBehavior::before_save(am);

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
ActiveModelTrait, ColumnTrait, Delete, DeleteMany, DeleteOne, FromQueryResult, Insert, ActiveModelTrait, ColumnTrait, Delete, DeleteMany, DeleteOne, FromQueryResult, Insert,
ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, Related, RelationBuilder, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, Related,
RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne, RelationBuilder, RelationTrait, RelationType, Select, Update, UpdateMany, UpdateOne,
}; };
use sea_query::{Alias, Iden, IntoIden, IntoTableRef, IntoValueTuple, TableRef}; use sea_query::{Alias, Iden, IntoIden, IntoTableRef, IntoValueTuple, TableRef};
pub use sea_strum::IntoEnumIterator as Iterable; pub use sea_strum::IntoEnumIterator as Iterable;
@ -299,6 +299,8 @@ pub trait EntityTrait: EntityName {
fn insert<A>(model: A) -> Insert<A> fn insert<A>(model: A) -> Insert<A>
where where
A: ActiveModelTrait<Entity = Self>, A: ActiveModelTrait<Entity = Self>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
Insert::one(model) Insert::one(model)
} }
@ -352,6 +354,8 @@ pub trait EntityTrait: EntityName {
where where
A: ActiveModelTrait<Entity = Self>, A: ActiveModelTrait<Entity = Self>,
I: IntoIterator<Item = A>, I: IntoIterator<Item = A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
Insert::many(models) Insert::many(models)
} }

View File

@ -2,8 +2,9 @@ pub use crate::{
error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType, error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType,
DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity,
DeriveEntityModel, DeriveModel, DerivePrimaryKey, DeriveRelation, EntityName, EntityTrait, DeriveEntityModel, DeriveModel, DerivePrimaryKey, DeriveRelation, EntityName, EntityTrait,
EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, ModelTrait, PrimaryKeyToColumn, EnumIter, ForeignKeyAction, Iden, IdenStatic, IntoActiveModel, Linked, ModelTrait,
PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, Value, PrimaryKeyToColumn, PrimaryKeyTrait, PrimaryKeyValue, QueryFilter, QueryResult, Related,
RelationDef, RelationTrait, Select, Value,
}; };
#[cfg(feature = "with-json")] #[cfg(feature = "with-json")]

View File

@ -1,18 +1,11 @@
use super::{ColumnTrait, IdenStatic, Iterable}; use super::{ColumnTrait, IdenStatic, Iterable};
use crate::{TryFromU64, TryGetableMany}; use crate::{ActiveModelTrait, EntityTrait, TryFromU64, TryGetableMany};
use sea_query::IntoValueTuple; use sea_query::IntoValueTuple;
use std::fmt::Debug; use std::fmt::Debug;
//LINT: composite primary key cannot auto increment //LINT: composite primary key cannot auto increment
pub trait PrimaryKeyTrait: IdenStatic + Iterable { pub trait PrimaryKeyTrait: IdenStatic + Iterable {
type ValueType: Sized type ValueType: Sized + Send + Debug + PartialEq + IntoValueTuple + TryGetableMany + TryFromU64;
+ Send
+ Default
+ Debug
+ PartialEq
+ IntoValueTuple
+ TryGetableMany
+ TryFromU64;
fn auto_increment() -> bool; fn auto_increment() -> bool;
} }
@ -26,3 +19,12 @@ pub trait PrimaryKeyToColumn {
where where
Self: Sized; Self: Sized;
} }
pub trait PrimaryKeyValue<E>
where
E: EntityTrait,
{
fn get_primary_key_value<A>(active_model: A) -> <E::PrimaryKey as PrimaryKeyTrait>::ValueType
where
A: ActiveModelTrait<Entity = E>;
}

View File

@ -5,11 +5,12 @@ use crate::{
use sea_query::InsertStatement; use sea_query::InsertStatement;
use std::{future::Future, marker::PhantomData}; use std::{future::Future, marker::PhantomData};
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct Inserter<A> pub struct Inserter<A>
where where
A: ActiveModelTrait, A: ActiveModelTrait,
{ {
primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
query: InsertStatement, query: InsertStatement,
model: PhantomData<A>, model: PhantomData<A>,
} }
@ -48,7 +49,7 @@ where
); );
} }
} }
Inserter::<A>::new(query).exec(db) Inserter::<A>::new(self.primary_key, query).exec(db)
// TODO: return primary key if extracted before, otherwise use InsertResult // TODO: return primary key if extracted before, otherwise use InsertResult
} }
} }
@ -57,8 +58,12 @@ impl<A> Inserter<A>
where where
A: ActiveModelTrait, A: ActiveModelTrait,
{ {
pub fn new(query: InsertStatement) -> Self { pub fn new(
primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
query: InsertStatement,
) -> Self {
Self { Self {
primary_key,
query, query,
model: PhantomData, model: PhantomData,
} }
@ -72,12 +77,13 @@ where
A: 'a, A: 'a,
{ {
let builder = db.get_database_backend(); 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 // Only Statement impl Send
async fn exec_insert<A>( async fn exec_insert<A>(
primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
statement: Statement, statement: Statement,
db: &DatabaseConnection, db: &DatabaseConnection,
) -> Result<InsertResult<A>, DbErr> ) -> Result<InsertResult<A>, DbErr>
@ -86,7 +92,7 @@ where
{ {
type PrimaryKey<A> = <<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey; type PrimaryKey<A> = <<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey;
type ValueTypeOf<A> = <PrimaryKey<A> as PrimaryKeyTrait>::ValueType; type ValueTypeOf<A> = <PrimaryKey<A> as PrimaryKeyTrait>::ValueType;
let last_insert_id = match db { let last_insert_id_opt = match db {
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
DatabaseConnection::SqlxPostgresPoolConnection(conn) => { DatabaseConnection::SqlxPostgresPoolConnection(conn) => {
use crate::{sea_query::Iden, Iterable}; use crate::{sea_query::Iden, Iterable};
@ -94,14 +100,19 @@ where
.map(|col| col.to_string()) .map(|col| col.to_string())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let res = conn.query_one(statement).await?.unwrap(); 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(); let last_insert_id = db.execute(statement).await?.last_insert_id();
ValueTypeOf::<A>::try_from_u64(last_insert_id) ValueTypeOf::<A>::try_from_u64(last_insert_id).ok()
.ok()
.unwrap_or_default()
} }
}; };
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 }) Ok(InsertResult { last_insert_id })
} }

View File

@ -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 core::marker::PhantomData;
use sea_query::InsertStatement; use sea_query::InsertStatement;
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct Insert<A> pub struct Insert<A>
where where
A: ActiveModelTrait, A: ActiveModelTrait,
{ {
pub(crate) query: InsertStatement, pub(crate) query: InsertStatement,
pub(crate) columns: Vec<bool>, pub(crate) columns: Vec<bool>,
pub(crate) primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
pub(crate) model: PhantomData<A>, pub(crate) model: PhantomData<A>,
} }
@ -31,6 +35,7 @@ where
.into_table(A::Entity::default().table_ref()) .into_table(A::Entity::default().table_ref())
.to_owned(), .to_owned(),
columns: Vec::new(), columns: Vec::new(),
primary_key: None,
model: PhantomData, model: PhantomData,
} }
} }
@ -68,6 +73,8 @@ where
pub fn one<M>(m: M) -> Insert<A> pub fn one<M>(m: M) -> Insert<A>
where where
M: IntoActiveModel<A>, M: IntoActiveModel<A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
Self::new().add(m) Self::new().add(m)
} }
@ -97,6 +104,8 @@ where
where where
M: IntoActiveModel<A>, M: IntoActiveModel<A>,
I: IntoIterator<Item = M>, I: IntoIterator<Item = M>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
Self::new().add_many(models) Self::new().add_many(models)
} }
@ -105,8 +114,16 @@ where
pub fn add<M>(mut self, m: M) -> Self pub fn add<M>(mut self, m: M) -> Self
where where
M: IntoActiveModel<A>, M: IntoActiveModel<A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
let mut am: A = m.into_active_model(); let mut am: A = m.into_active_model();
self.primary_key =
if !<<A::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::auto_increment() {
Some(<<A::Entity as EntityTrait>::PrimaryKey as PrimaryKeyValue<A::Entity>>::get_primary_key_value::<A>(am.clone()))
} else {
None
};
let mut columns = Vec::new(); let mut columns = Vec::new();
let mut values = Vec::new(); let mut values = Vec::new();
let columns_empty = self.columns.is_empty(); let columns_empty = self.columns.is_empty();
@ -132,6 +149,8 @@ where
where where
M: IntoActiveModel<A>, M: IntoActiveModel<A>,
I: IntoIterator<Item = M>, I: IntoIterator<Item = M>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{ {
for model in models.into_iter() { for model in models.into_iter() {
self = self.add(model); self = self.add(model);