mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
feat(core): add TypeNotCompatible error variants to Decode and Encode Error
This commit is contained in:
parent
2934a18af4
commit
ecb4bd0281
@ -3,13 +3,12 @@ use std::fmt::{self, Display, Formatter};
|
||||
use std::str::Utf8Error;
|
||||
|
||||
use crate::database::HasRawValue;
|
||||
use crate::Database;
|
||||
use crate::{Database, Type, TypeInfo};
|
||||
|
||||
/// A type that can be decoded from a SQL value.
|
||||
pub trait Decode<'r, Db: Database>: Send + Sync {
|
||||
fn decode(value: <Db as HasRawValue<'r>>::RawValue) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
pub trait Decode<'r, Db: Database>: Sized + Send + Sync {
|
||||
/// Decode the SQL value into the target type.
|
||||
fn decode(value: <Db as HasRawValue<'r>>::RawValue) -> Result<Self>;
|
||||
}
|
||||
|
||||
/// A type that can be decoded from a SQL value, without borrowing any data
|
||||
@ -23,6 +22,11 @@ impl<T, Db: Database> DecodeOwned<Db> for T where T: for<'r> Decode<'r, Db> {}
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
TypeNotCompatible {
|
||||
rust_type_name: &'static str,
|
||||
sql_type_name: &'static str,
|
||||
},
|
||||
|
||||
/// An unexpected SQL `NULL` was encountered during decoding.
|
||||
///
|
||||
/// To decode potentially `NULL` values, wrap the target type in `Option`.
|
||||
@ -48,6 +52,14 @@ impl Display for Error {
|
||||
match self {
|
||||
Self::UnexpectedNull => f.write_str("unexpected null; try decoding as an `Option`"),
|
||||
|
||||
Self::TypeNotCompatible { rust_type_name, sql_type_name } => {
|
||||
write!(
|
||||
f,
|
||||
"Rust type `{}` is not compatible with SQL type `{}`",
|
||||
rust_type_name, sql_type_name
|
||||
)
|
||||
}
|
||||
|
||||
Self::NotUtf8(error) => {
|
||||
write!(f, "{}", error)
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ use std::error::Error as StdError;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use crate::database::HasOutput;
|
||||
use crate::Database;
|
||||
use crate::{Database, Type, TypeInfo};
|
||||
|
||||
/// A type that can be encoded into a SQL value.
|
||||
pub trait Encode<Db: Database>: Send + Sync {
|
||||
@ -21,6 +21,11 @@ impl<T: Encode<Db>, Db: Database> Encode<Db> for &T {
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
TypeNotCompatible {
|
||||
rust_type_name: &'static str,
|
||||
sql_type_name: &'static str,
|
||||
},
|
||||
|
||||
/// A general error raised while encoding a value.
|
||||
Custom(Box<dyn StdError + Send + Sync>),
|
||||
}
|
||||
@ -35,6 +40,14 @@ impl Error {
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::TypeNotCompatible { rust_type_name, sql_type_name } => {
|
||||
write!(
|
||||
f,
|
||||
"Rust type `{}` is not compatible with SQL type `{}`",
|
||||
rust_type_name, sql_type_name
|
||||
)
|
||||
}
|
||||
|
||||
Self::Custom(error) => {
|
||||
write!(f, "{}", error)
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ mod database;
|
||||
|
||||
pub use database::DatabaseError;
|
||||
|
||||
use crate::Column;
|
||||
|
||||
/// Specialized `Result` type returned from fallible methods within SQLx.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@ -89,6 +91,15 @@ impl Error {
|
||||
pub fn opt_msg(message: impl Into<Cow<'static, str>>) -> Self {
|
||||
Self::ConnectOptions { message: message.into(), source: None }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn column_decode(column: &impl Column, source: DecodeError) -> Self {
|
||||
crate::Error::ColumnDecode {
|
||||
source,
|
||||
column_index: column.index(),
|
||||
column_name: column.name().to_owned().into_boxed_str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
@ -107,41 +118,45 @@ impl Display for Error {
|
||||
}
|
||||
|
||||
Self::RowNotFound => {
|
||||
f.write_str("no row returned by a query required to return at least one row")
|
||||
f.write_str("No row returned by a query required to return at least one row")
|
||||
}
|
||||
|
||||
Self::Closed => f.write_str("connection or pool is closed"),
|
||||
Self::Closed => f.write_str("Connection or pool is closed"),
|
||||
|
||||
Self::Decode(error) => {
|
||||
write!(f, "decode: {}", error)
|
||||
write!(f, "Decode: {}", error)
|
||||
}
|
||||
|
||||
Self::Encode(error) => {
|
||||
write!(f, "encode: {}", error)
|
||||
write!(f, "Encode: {}", error)
|
||||
}
|
||||
|
||||
Self::ColumnIndexOutOfBounds { index, len } => {
|
||||
write!(
|
||||
f,
|
||||
"column index out of bounds: the len is {}, but the index is {}",
|
||||
"Column index out of bounds: the len is {}, but the index is {}",
|
||||
len, index
|
||||
)
|
||||
}
|
||||
|
||||
Self::ColumnNotFound { name } => {
|
||||
write!(f, "no column found for name `{}`", name)
|
||||
write!(f, "No column found for name `{}`", name)
|
||||
}
|
||||
|
||||
Self::ColumnDecode { column_index, column_name, source } => {
|
||||
write!(f, "decode column {} `{}`: {}", column_index, column_name, source)
|
||||
if column_name.is_empty() {
|
||||
write!(f, "Decode column {}: {}", column_index, source)
|
||||
} else {
|
||||
write!(f, "Decode column {} `{}`: {}", column_index, column_name, source)
|
||||
}
|
||||
}
|
||||
|
||||
Self::ParameterEncode { parameter: Either::Left(index), source } => {
|
||||
write!(f, "encode parameter {}: {}", index, source)
|
||||
write!(f, "Encode parameter {}: {}", index, source)
|
||||
}
|
||||
|
||||
Self::ParameterEncode { parameter: Either::Right(name), source } => {
|
||||
write!(f, "encode parameter `{}`: {}", name, source)
|
||||
write!(f, "Encode parameter `{}`: {}", name, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,5 +34,5 @@ pub trait TypeInfo {
|
||||
///
|
||||
/// Common type names include `VARCHAR`, `INTEGER`, and `BIGINT`.
|
||||
///
|
||||
fn name(&self) -> &str;
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user