Rework DbErr

This commit is contained in:
Chris Tsang 2021-06-30 23:42:12 +08:00
parent dd8d8c3431
commit f5ac84f915
9 changed files with 70 additions and 66 deletions

View File

@ -75,7 +75,7 @@ impl MockDatabaseTrait for MockDatabase {
result: ExecResultHolder::Mock(std::mem::take(&mut self.exec_results[counter])),
})
} else {
Err(DbErr::Exec)
Err(DbErr::Exec("`exec_results` buffer is empty.".to_owned()))
}
}
@ -93,7 +93,7 @@ impl MockDatabaseTrait for MockDatabase {
})
.collect())
} else {
Err(DbErr::Query)
Err(DbErr::Query("`query_results` buffer is empty.".to_owned()))
}
}

View File

@ -29,6 +29,6 @@ impl Database {
if crate::MockDatabaseConnector::accepts(string) {
return crate::MockDatabaseConnector::connect(string).await;
}
Err(DbErr::Conn)
Err(DbErr::Conn(format!("The connection string '{}' has no supporting driver.", string)))
}
}

View File

@ -1,5 +1,7 @@
#[cfg(feature = "mock")]
mod mock;
#[cfg(feature = "sqlx-dep")]
mod sqlx_common;
#[cfg(feature = "sqlx-mysql")]
mod sqlx_mysql;
#[cfg(feature = "sqlx-sqlite")]
@ -7,6 +9,8 @@ mod sqlx_sqlite;
#[cfg(feature = "mock")]
pub use mock::*;
#[cfg(feature = "sqlx-dep")]
pub use sqlx_common::*;
#[cfg(feature = "sqlx-mysql")]
pub use sqlx_mysql::*;
#[cfg(feature = "sqlx-sqlite")]

View File

@ -0,0 +1,9 @@
use crate::DbErr;
pub fn sqlx_error_to_exec_err(err: sqlx::Error) -> DbErr {
DbErr::Exec(err.to_string())
}
pub fn sqlx_error_to_query_err(err: sqlx::Error) -> DbErr {
DbErr::Query(err.to_string())
}

View File

@ -8,6 +8,8 @@ use sea_query_driver_mysql::bind_query;
use crate::{debug_print, error::*, executor::*, DatabaseConnection, Statement};
use super::sqlx_common::*;
pub struct SqlxMySqlConnector;
pub struct SqlxMySqlPoolConnection {
@ -25,7 +27,7 @@ impl SqlxMySqlConnector {
SqlxMySqlPoolConnection { pool },
))
} else {
Err(DbErr::Conn)
Err(DbErr::Conn("Failed to connect.".to_owned()))
}
}
}
@ -42,11 +44,13 @@ impl SqlxMySqlPoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(res) = query.execute(conn).await {
return Ok(res.into());
match query.execute(conn).await {
Ok(res) => Ok(res.into()),
Err(err) => Err(sqlx_error_to_exec_err(err)),
}
} else {
Err(DbErr::Exec("Failed to acquire connection from pool.".to_owned()))
}
Err(DbErr::Exec)
}
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
@ -54,13 +58,15 @@ impl SqlxMySqlPoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(row) = query.fetch_one(conn).await {
Ok(Some(row.into()))
} else {
Ok(None)
match query.fetch_one(conn).await {
Ok(row) => Ok(Some(row.into())),
Err(err) => match err {
sqlx::Error::RowNotFound => Ok(None),
_ => Err(DbErr::Query(err.to_string())),
},
}
} else {
Err(DbErr::Query)
Err(DbErr::Query("Failed to acquire connection from pool.".to_owned()))
}
}
@ -69,11 +75,13 @@ impl SqlxMySqlPoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(rows) = query.fetch_all(conn).await {
return Ok(rows.into_iter().map(|r| r.into()).collect());
match query.fetch_all(conn).await {
Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()),
Err(err) => Err(sqlx_error_to_query_err(err)),
}
} else {
Err(DbErr::Query("Failed to acquire connection from pool.".to_owned()))
}
Err(DbErr::Query)
}
}

View File

@ -8,6 +8,8 @@ use sea_query_driver_sqlite::bind_query;
use crate::{debug_print, error::*, executor::*, DatabaseConnection, Statement};
use super::sqlx_common::*;
pub struct SqlxSqliteConnector;
pub struct SqlxSqlitePoolConnection {
@ -25,7 +27,7 @@ impl SqlxSqliteConnector {
SqlxSqlitePoolConnection { pool },
))
} else {
Err(DbErr::Conn)
Err(DbErr::Conn("Failed to connect.".to_owned()))
}
}
}
@ -42,11 +44,13 @@ impl SqlxSqlitePoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(res) = query.execute(conn).await {
return Ok(res.into());
match query.execute(conn).await {
Ok(res) => Ok(res.into()),
Err(err) => Err(sqlx_error_to_exec_err(err)),
}
} else {
Err(DbErr::Exec("Failed to acquire connection from pool.".to_owned()))
}
Err(DbErr::Exec)
}
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
@ -54,13 +58,15 @@ impl SqlxSqlitePoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(row) = query.fetch_one(conn).await {
Ok(Some(row.into()))
} else {
Ok(None)
match query.fetch_one(conn).await {
Ok(row) => Ok(Some(row.into())),
Err(err) => match err {
sqlx::Error::RowNotFound => Ok(None),
_ => Err(DbErr::Query(err.to_string())),
},
}
} else {
Err(DbErr::Query)
Err(DbErr::Query("Failed to acquire connection from pool.".to_owned()))
}
}
@ -69,11 +75,13 @@ impl SqlxSqlitePoolConnection {
let query = sqlx_query(&stmt);
if let Ok(conn) = &mut self.pool.acquire().await {
if let Ok(rows) = query.fetch_all(conn).await {
return Ok(rows.into_iter().map(|r| r.into()).collect());
match query.fetch_all(conn).await {
Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()),
Err(err) => Err(sqlx_error_to_query_err(err)),
}
} else {
Err(DbErr::Query("Failed to acquire connection from pool.".to_owned()))
}
Err(DbErr::Query)
}
}

View File

@ -223,11 +223,11 @@ where
// TODO: if the entity does not have auto increment primary key, then last_insert_id is a wrong value
if <E::PrimaryKey as PrimaryKeyTrait>::auto_increment() && res.last_insert_id != 0 {
let find = E::find_by_id(res.last_insert_id).one(db);
let res = find.await;
let model: Option<E::Model> = res?;
let found = find.await;
let model: Option<E::Model> = found?;
match model {
Some(model) => Ok(model.into_active_model()),
None => Err(DbErr::Exec),
None => Err(DbErr::Exec(format!("Failed to find inserted item: {} {}", E::default().to_string(), res.last_insert_id))),
}
} else {
Ok(A::default())

View File

@ -1,41 +1,16 @@
use std::{error, fmt};
#[derive(Debug)]
pub enum DbErr {
Conn,
Exec,
Query,
#[cfg(feature = "sqlx-dep")]
Sqlx(sqlx::Error),
Conn(String),
Exec(String),
Query(String),
}
impl fmt::Display for DbErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl std::fmt::Display for DbErr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Conn => write!(f, "{:?}", "Connection Error"),
Self::Exec => write!(f, "{:?}", "Execution Error"),
Self::Query => write!(f, "{:?}", "Query Error"),
#[cfg(feature = "sqlx-dep")]
Self::Sqlx(e) => write!(f, "{:?}", e),
Self::Conn(s) => write!(f, "Connection Error: {}", s),
Self::Exec(s) => write!(f, "Execution Error: {}", s),
Self::Query(s) => write!(f, "Query Error: {}", s),
}
}
}
impl error::Error for DbErr {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Conn => None,
Self::Exec => None,
Self::Query => None,
#[cfg(feature = "sqlx-dep")]
Self::Sqlx(e) => Some(e),
}
}
}
#[cfg(feature = "sqlx-dep")]
impl From<sqlx::Error> for DbErr {
fn from(sqlx_err: sqlx::Error) -> Self {
Self::Sqlx(sqlx_err)
}
}

View File

@ -56,12 +56,12 @@ macro_rules! try_getable_all {
#[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => {
use sqlx::Row;
Ok(row.try_get(column.as_str())?)
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err)
}
#[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(row) => {
use sqlx::Row;
Ok(row.try_get(column.as_str())?)
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err)
}
#[cfg(feature = "mock")]
QueryResultRow::Mock(row) => Ok(row.try_get(column.as_str())?),
@ -109,7 +109,7 @@ macro_rules! try_getable_mysql {
#[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => {
use sqlx::Row;
Ok(row.try_get(column.as_str())?)
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err)
}
#[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(_) => {