diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index a283ddf3..9c45413f 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -110,8 +110,11 @@ impl From for ExecResult { } } -pub(crate) fn query_result_into_exec_result(res: QueryResult) -> Result { - let last_insert_id: i32 = res.try_get("", "last_insert_id")?; +pub(crate) fn query_result_into_exec_result(res: QueryResult) -> Result +where + T: TryGetable, +{ + let last_insert_id: T = res.try_get("", "last_insert_id")?; Ok(ExecResult { result: ExecResultHolder::SqlxPostgres { last_insert_id: last_insert_id as u64, diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 54bf037b..612e285d 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -221,7 +221,11 @@ where let exec = E::insert(am).exec(db); let res = exec.await?; // TODO: if the entity does not have auto increment primary key, then last_insert_id is a wrong value - if ::auto_increment() && res.last_insert_id != 0 { + // FIXME: Assumed valid last_insert_id is not equals to Default::default() + if ::auto_increment() + && res.last_insert_id != ::ValueType::default() + { + let last_insert_id = res.last_insert_id.to_string(); let find = E::find_by_id(res.last_insert_id).one(db); let found = find.await; let model: Option = found?; @@ -230,7 +234,7 @@ where None => Err(DbErr::Exec(format!( "Failed to find inserted item: {} {}", E::default().to_string(), - res.last_insert_id + last_insert_id ))), } } else { diff --git a/src/entity/primary_key.rs b/src/entity/primary_key.rs index a36b04e0..1d434c13 100644 --- a/src/entity/primary_key.rs +++ b/src/entity/primary_key.rs @@ -1,8 +1,11 @@ use super::{ColumnTrait, IdenStatic, Iterable}; +use crate::TryGetable; +use sea_query::IntoValueTuple; +use std::fmt::{Debug, Display}; //LINT: composite primary key cannot auto increment pub trait PrimaryKeyTrait: IdenStatic + Iterable { - type ValueType: Sized; + type ValueType: Sized + Default + Debug + Display + PartialEq + IntoValueTuple + TryGetable; fn auto_increment() -> bool; } diff --git a/src/executor/insert.rs b/src/executor/insert.rs index 9414fea6..a644d6e9 100644 --- a/src/executor/insert.rs +++ b/src/executor/insert.rs @@ -1,15 +1,24 @@ -use crate::{error::*, ActiveModelTrait, DatabaseConnection, Insert, Statement}; +use crate::{ + error::*, ActiveModelTrait, DatabaseConnection, EntityTrait, Insert, PrimaryKeyTrait, Statement, +}; use sea_query::InsertStatement; -use std::future::Future; +use std::{future::Future, marker::PhantomData}; #[derive(Clone, Debug)] -pub struct Inserter { +pub struct Inserter +where + A: ActiveModelTrait, +{ query: InsertStatement, + model: PhantomData, } -#[derive(Clone, Debug)] -pub struct InsertResult { - pub last_insert_id: u64, +#[derive(Debug)] +pub struct InsertResult +where + A: ActiveModelTrait, +{ + pub last_insert_id: <<::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType, } impl Insert @@ -17,10 +26,13 @@ where A: ActiveModelTrait, { #[allow(unused_mut)] - pub fn exec( + pub fn exec<'a>( self, - db: &DatabaseConnection, - ) -> impl Future> + '_ { + db: &'a DatabaseConnection, + ) -> impl Future, DbErr>> + 'a + where + A: 'a, + { // so that self is dropped before entering await let mut query = self.query; #[cfg(feature = "sqlx-postgres")] @@ -35,26 +47,41 @@ where ); } } - Inserter::new(query).exec(db) + Inserter::::new(query).exec(db) } } -impl Inserter { +impl Inserter +where + A: ActiveModelTrait, +{ pub fn new(query: InsertStatement) -> Self { - Self { query } + Self { + query, + model: PhantomData, + } } - pub fn exec( + pub fn exec<'a>( self, - db: &DatabaseConnection, - ) -> impl Future> + '_ { + db: &'a DatabaseConnection, + ) -> impl Future, DbErr>> + 'a + where + A: 'a, + { let builder = db.get_database_backend(); exec_insert(builder.build(&self.query), db) } } // Only Statement impl Send -async fn exec_insert(statement: Statement, db: &DatabaseConnection) -> Result { +async fn exec_insert( + statement: Statement, + db: &DatabaseConnection, +) -> Result, DbErr> +where + A: ActiveModelTrait, +{ // TODO: Postgres instead use query_one + returning clause let result = match db { #[cfg(feature = "sqlx-postgres")]