From 23ac9581421d2f931eb62d6594fcdb30cb371f5c Mon Sep 17 00:00:00 2001 From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com> Date: Tue, 12 Jul 2022 00:16:03 +0900 Subject: [PATCH] include column name in TryGetError::Null (#853) * include column name in TryGetError::Null * remove prefix --- src/executor/query.rs | 121 +++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 48 deletions(-) diff --git a/src/executor/query.rs b/src/executor/query.rs index ee452f51..bddb6db5 100644 --- a/src/executor/query.rs +++ b/src/executor/query.rs @@ -33,14 +33,16 @@ pub enum TryGetError { /// A database error was encountered as defined in [crate::DbErr] DbErr(DbErr), /// A null value was encountered - Null, + Null(String), } impl From for DbErr { fn from(e: TryGetError) -> DbErr { match e { TryGetError::DbErr(e) => e, - TryGetError::Null => DbErr::Query("error occurred while decoding: Null".to_owned()), + TryGetError::Null(s) => DbErr::Query( + format!("error occurred while decoding {}: Null", s) + ), } } } @@ -89,7 +91,7 @@ impl TryGetable for Option { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { match T::try_get(res, pre, col) { Ok(v) => Ok(Some(v)), - Err(TryGetError::Null) => Ok(None), + Err(TryGetError::Null(_)) => Ok(None), Err(e) => Err(e), } } @@ -107,27 +109,27 @@ macro_rules! try_getable_all { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "mock")] #[allow(unused_variables)] QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -141,14 +143,15 @@ macro_rules! try_getable_unsigned { ( $type: ty ) => { impl TryGetable for $type { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { - let _column = format!("{}{}", pre, col); + #[allow(unused_variables)] + let column = format!("{}{}", pre, col); match &res.row { #[cfg(feature = "sqlx-mysql")] QueryResultRow::SqlxMySql(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(_) => { @@ -157,15 +160,15 @@ macro_rules! try_getable_unsigned { #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "mock")] #[allow(unused_variables)] - QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| { + QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -179,14 +182,15 @@ macro_rules! try_getable_mysql { ( $type: ty ) => { impl TryGetable for $type { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { - let _column = format!("{}{}", pre, col); + #[allow(unused_variables)] + let column = format!("{}{}", pre, col); match &res.row { #[cfg(feature = "sqlx-mysql")] QueryResultRow::SqlxMySql(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(_) => { @@ -198,9 +202,9 @@ macro_rules! try_getable_mysql { } #[cfg(feature = "mock")] #[allow(unused_variables)] - QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| { + QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -215,38 +219,39 @@ macro_rules! try_getable_date_time { ( $type: ty ) => { impl TryGetable for $type { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { - let _column = format!("{}{}", pre, col); + #[allow(unused_variables)] + let column = format!("{}{}", pre, col); match &res.row { #[cfg(feature = "sqlx-mysql")] QueryResultRow::SqlxMySql(row) => { use chrono::{DateTime, Utc}; use sqlx::Row; - row.try_get::>, _>(_column.as_str()) + row.try_get::>, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) .map(|v| v.into()) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { use chrono::{DateTime, Utc}; use sqlx::Row; - row.try_get::>, _>(_column.as_str()) + row.try_get::>, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) .map(|v| v.into()) } #[cfg(feature = "mock")] #[allow(unused_variables)] - QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| { + QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -269,14 +274,14 @@ macro_rules! try_getable_time { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(_) => { @@ -286,7 +291,7 @@ macro_rules! try_getable_time { #[allow(unused_variables)] QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -356,14 +361,14 @@ impl TryGetable for Decimal { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { @@ -378,14 +383,14 @@ impl TryGetable for Decimal { "Failed to convert f64 into Decimal".to_owned(), )) }), - None => Err(TryGetError::Null), + None => Err(TryGetError::Null(column)), } } #[cfg(feature = "mock")] #[allow(unused_variables)] QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -398,14 +403,15 @@ try_getable_all!(uuid::Uuid); impl TryGetable for u32 { fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { - let _column = format!("{}{}", pre, col); + #[allow(unused_variables)] + let column = format!("{}{}", pre, col); match &res.row { #[cfg(feature = "sqlx-mysql")] QueryResultRow::SqlxMySql(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { @@ -413,23 +419,23 @@ impl TryGetable for u32 { // Since 0.6.0, SQLx has dropped direct mapping from PostgreSQL's OID to Rust's `u32`; // Instead, `u32` was wrapped by a `sqlx::Oid`. use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) .map(|oid| oid.0) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { use sqlx::Row; - row.try_get::, _>(_column.as_str()) + row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "mock")] #[allow(unused_variables)] - QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| { + QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }), #[allow(unreachable_patterns)] _ => unreachable!(), @@ -648,28 +654,28 @@ where use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-postgres")] QueryResultRow::SqlxPostgres(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "sqlx-sqlite")] QueryResultRow::SqlxSqlite(row) => { use sqlx::Row; row.try_get::, _>(column.as_str()) .map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e))) - .and_then(|opt| opt.ok_or(TryGetError::Null)) + .and_then(|opt| opt.ok_or(TryGetError::Null(column))) } #[cfg(feature = "mock")] QueryResultRow::Mock(row) => { row.try_get::(column.as_str()) .map_err(|e| { debug_print!("{:#?}", e.to_string()); - TryGetError::Null + TryGetError::Null(column) }) } #[allow(unreachable_patterns)] @@ -813,3 +819,22 @@ try_from_u64_err!(rust_decimal::Decimal); #[cfg(feature = "with-uuid")] try_from_u64_err!(uuid::Uuid); + +#[cfg(test)] +mod tests { + use super::{TryGetError}; + use crate::error::DbErr; + + #[test] + fn from_try_get_error() { + // TryGetError::DbErr + let expected = DbErr::Query("expected error message".to_owned()); + let try_get_error = TryGetError::DbErr(expected.clone()); + assert_eq!(DbErr::from(try_get_error), expected); + + // TryGetError::Null + let try_get_error = TryGetError::Null("column".to_owned()); + let expected = "error occurred while decoding column: Null".to_owned(); + assert_eq!(DbErr::from(try_get_error), DbErr::Query(expected)); + } +}