diff --git a/diesel/src/deserialize.rs b/diesel/src/deserialize.rs index 3525cb262d6f..217bc6742755 100644 --- a/diesel/src/deserialize.rs +++ b/diesel/src/deserialize.rs @@ -5,7 +5,6 @@ use std::result; use crate::backend::Backend; use crate::expression::select_by::SelectBy; -use crate::result::DeserializeFieldError; use crate::row::{NamedRow, Row}; use crate::sql_types::{SingleValue, SqlType, Untyped}; use crate::Selectable; @@ -543,13 +542,10 @@ where let field = row.get(0).ok_or(crate::result::UnexpectedEndOfRow)?; T::from_nullable_sql(field.value()).map_err(|e| { if e.is::() { - return e; + e + } else { + Box::new(crate::result::DeserializeFieldError::new(field, e)) } - - Box::new(DeserializeFieldError { - field_name: field.field_name().map(|s| s.to_string()), - error: e, - }) }) } } diff --git a/diesel/src/pg/connection/result.rs b/diesel/src/pg/connection/result.rs index 4b00f718dc37..b4f501669f3d 100644 --- a/diesel/src/pg/connection/result.rs +++ b/diesel/src/pg/connection/result.rs @@ -148,6 +148,7 @@ impl PgResult { ) } + #[inline(always)] // benchmarks indicate a ~1.7% improvement in instruction count for this pub(super) fn column_name(&self, col_idx: usize) -> Option<&str> { self.column_name_map .get_or_init(|| { diff --git a/diesel/src/pg/types/integers.rs b/diesel/src/pg/types/integers.rs index b1a56b0a3a6d..b75c4c495a62 100644 --- a/diesel/src/pg/types/integers.rs +++ b/diesel/src/pg/types/integers.rs @@ -23,10 +23,11 @@ impl ToSql for u32 { #[cfg(feature = "postgres_backend")] impl FromSql for i16 { + #[inline(always)] fn from_sql(value: PgValue<'_>) -> deserialize::Result { let mut bytes = value.as_bytes(); if bytes.len() < 2 { - return deserialize::Result::Err( + return emit_size_error( "Received less than 2 bytes while decoding an i16. \ Was an expression of a different type accidentally marked as SmallInt?" .into(), @@ -34,7 +35,7 @@ impl FromSql for i16 { } if bytes.len() > 2 { - return deserialize::Result::Err( + return emit_size_error( "Received more than 2 bytes while decoding an i16. \ Was an Integer expression accidentally marked as SmallInt?" .into(), @@ -48,21 +49,20 @@ impl FromSql for i16 { #[cfg(feature = "postgres_backend")] impl FromSql for i32 { + #[inline(always)] fn from_sql(value: PgValue<'_>) -> deserialize::Result { let mut bytes = value.as_bytes(); if bytes.len() < 4 { - return deserialize::Result::Err( + return emit_size_error( "Received less than 4 bytes while decoding an i32. \ - Was an SmallInt expression accidentally marked as Integer?" - .into(), + Was an SmallInt expression accidentally marked as Integer?", ); } if bytes.len() > 4 { - return deserialize::Result::Err( + return emit_size_error( "Received more than 4 bytes while decoding an i32. \ - Was an BigInt expression accidentally marked as Integer?" - .into(), + Was an BigInt expression accidentally marked as Integer?", ); } bytes @@ -71,12 +71,19 @@ impl FromSql for i32 { } } +#[cold] +#[inline(never)] +fn emit_size_error(var_name: &str) -> deserialize::Result { + deserialize::Result::Err(var_name.into()) +} + #[cfg(feature = "postgres_backend")] impl FromSql for i64 { + #[inline(always)] fn from_sql(value: PgValue<'_>) -> deserialize::Result { let mut bytes = value.as_bytes(); if bytes.len() < 8 { - return deserialize::Result::Err( + return emit_size_error( "Received less than 8 bytes while decoding an i64. \ Was an Integer expression accidentally marked as BigInt?" .into(), @@ -84,7 +91,7 @@ impl FromSql for i64 { } if bytes.len() > 8 { - return deserialize::Result::Err( + return emit_size_error( "Received more than 8 bytes while decoding an i64. \ Was an expression of a different type expression accidentally marked as BigInt?" .into(), diff --git a/diesel/src/result.rs b/diesel/src/result.rs index 9ee94d8a6bba..acf12423b068 100644 --- a/diesel/src/result.rs +++ b/diesel/src/result.rs @@ -466,6 +466,20 @@ pub struct DeserializeFieldError { pub error: Box, } +impl DeserializeFieldError { + #[cold] + pub(crate) fn new<'a, F, DB>(field: F, error: Box) -> Self + where + DB: crate::backend::Backend, + F: crate::row::Field<'a, DB>, + { + DeserializeFieldError { + field_name: field.field_name().map(|s| s.to_string()), + error, + } + } +} + impl StdError for DeserializeFieldError { fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&*self.error) diff --git a/diesel_bench/Cargo.toml b/diesel_bench/Cargo.toml index 990d2d1c93ad..f788892eb3af 100644 --- a/diesel_bench/Cargo.toml +++ b/diesel_bench/Cargo.toml @@ -71,6 +71,7 @@ fast_run = [] [profile.release] lto = true +debug = true codegen-units = 1 [patch.crates-io]