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::{
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<Self, DbErr>
where
<Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
<<Self as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<Self as ActiveModelTrait>::Entity>,
{
let am = self;
let exec = <Self::Entity as EntityTrait>::insert(am).exec(db);
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)
.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 = <Self::Entity as EntityTrait>::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,
<Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
<<Self as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<Self as ActiveModelTrait>::Entity>,
{
let mut am = self;
am = ActiveModelBehavior::before_save(am);

View File

@ -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<A>(model: A) -> Insert<A>
where
A: ActiveModelTrait<Entity = Self>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
Insert::one(model)
}
@ -352,6 +354,8 @@ pub trait EntityTrait: EntityName {
where
A: ActiveModelTrait<Entity = Self>,
I: IntoIterator<Item = A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
Insert::many(models)
}

View File

@ -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")]

View File

@ -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<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 std::{future::Future, marker::PhantomData};
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct Inserter<A>
where
A: ActiveModelTrait,
{
primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
query: InsertStatement,
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
}
}
@ -57,8 +58,12 @@ impl<A> Inserter<A>
where
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 {
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<A>(
primary_key: Option<<<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType>,
statement: Statement,
db: &DatabaseConnection,
) -> Result<InsertResult<A>, DbErr>
@ -86,7 +92,7 @@ where
{
type PrimaryKey<A> = <<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey;
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")]
DatabaseConnection::SqlxPostgresPoolConnection(conn) => {
use crate::{sea_query::Iden, Iterable};
@ -94,14 +100,19 @@ where
.map(|col| col.to_string())
.collect::<Vec<_>>();
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::<A>::try_from_u64(last_insert_id)
.ok()
.unwrap_or_default()
ValueTypeOf::<A>::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 })
}

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 sea_query::InsertStatement;
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct Insert<A>
where
A: ActiveModelTrait,
{
pub(crate) query: InsertStatement,
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>,
}
@ -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: M) -> Insert<A>
where
M: IntoActiveModel<A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
Self::new().add(m)
}
@ -97,6 +104,8 @@ where
where
M: IntoActiveModel<A>,
I: IntoIterator<Item = M>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
Self::new().add_many(models)
}
@ -105,8 +114,16 @@ where
pub fn add<M>(mut self, m: M) -> Self
where
M: IntoActiveModel<A>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
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 values = Vec::new();
let columns_empty = self.columns.is_empty();
@ -132,6 +149,8 @@ where
where
M: IntoActiveModel<A>,
I: IntoIterator<Item = M>,
<<A as ActiveModelTrait>::Entity as EntityTrait>::PrimaryKey:
PrimaryKeyValue<<A as ActiveModelTrait>::Entity>,
{
for model in models.into_iter() {
self = self.add(model);