Skip to content

Commit 76a804b

Browse files
lovasoacursoragent
andauthored
Sqlx type info crash (#49)
* Refactor: Improve MismatchedTypeError for Any type Co-authored-by: contact <contact@ophir.dev> * Refactor rust_sql_type to use is_any_db helper Co-authored-by: contact <contact@ophir.dev> * Force `DB` type instantiation in `is_any_db` for type system checks. Co-authored-by: contact <contact@ophir.dev> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 645fd0d commit 76a804b

1 file changed

Lines changed: 55 additions & 4 deletions

File tree

sqlx-core/src/error.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,49 @@ pub struct MismatchedTypeError {
4141
pub source: Option<BoxDynError>,
4242
}
4343

44+
fn rust_sql_type<DB: Database, T: Type<DB>>() -> String {
45+
if is_any_db::<DB>() {
46+
return "<unknown>".to_string();
47+
}
48+
49+
T::type_info().name().to_string()
50+
}
51+
52+
#[cfg(all(
53+
feature = "any",
54+
any(
55+
feature = "postgres",
56+
feature = "mysql",
57+
feature = "mssql",
58+
feature = "sqlite",
59+
feature = "odbc"
60+
)
61+
))]
62+
fn is_any_db<DB: Database>() -> bool {
63+
std::any::TypeId::of::<DB>() == std::any::TypeId::of::<crate::any::Any>()
64+
}
65+
66+
#[cfg(not(all(
67+
feature = "any",
68+
any(
69+
feature = "postgres",
70+
feature = "mysql",
71+
feature = "mssql",
72+
feature = "sqlite",
73+
feature = "odbc"
74+
)
75+
)))]
76+
fn is_any_db<DB: Database>() -> bool {
77+
let _ = std::any::TypeId::of::<DB>();
78+
false
79+
}
80+
4481
impl MismatchedTypeError {
4582
/// Create a new mismatched type error without a source.
4683
pub fn new<DB: Database, T: Type<DB>>(ty: &DB::TypeInfo) -> Self {
4784
Self {
4885
rust_type: type_name::<T>().to_string(),
49-
rust_sql_type: T::type_info().name().to_string(),
86+
rust_sql_type: rust_sql_type::<DB, T>(),
5087
sql_type: ty.name().to_string(),
5188
source: None,
5289
}
@@ -56,7 +93,7 @@ impl MismatchedTypeError {
5693
pub fn with_source<DB: Database, T: Type<DB>>(ty: &DB::TypeInfo, source: BoxDynError) -> Self {
5794
Self {
5895
rust_type: type_name::<T>().to_string(),
59-
rust_sql_type: T::type_info().name().to_string(),
96+
rust_sql_type: rust_sql_type::<DB, T>(),
6097
sql_type: ty.name().to_string(),
6198
source: Some(source),
6299
}
@@ -182,19 +219,33 @@ impl Error {
182219
}
183220

184221
pub(crate) fn mismatched_types<DB: Database, T: Type<DB>>(ty: &DB::TypeInfo) -> BoxDynError {
222+
let rust_sql_type = rust_sql_type::<DB, T>();
185223
Box::new(MismatchedTypeError {
186224
rust_type: format!(
187225
"{} ({}compatible with SQL type `{}`)",
188226
type_name::<T>(),
189227
if T::compatible(ty) { "" } else { "in" },
190-
T::type_info().name()
228+
rust_sql_type
191229
),
192-
rust_sql_type: T::type_info().name().to_string(),
230+
rust_sql_type,
193231
sql_type: ty.name().to_string(),
194232
source: None,
195233
})
196234
}
197235

236+
#[cfg(all(test, feature = "any", feature = "postgres"))]
237+
mod tests {
238+
use crate::any::Any;
239+
use crate::error::mismatched_types;
240+
use crate::postgres::PgTypeInfo;
241+
242+
#[test]
243+
fn mismatched_types_any_does_not_panic() {
244+
let ty = crate::any::AnyTypeInfo::from(PgTypeInfo::with_name("TEXT"));
245+
assert!(std::panic::catch_unwind(|| mismatched_types::<Any, i32>(&ty)).is_ok());
246+
}
247+
}
248+
198249
/// An error that was returned from the database.
199250
pub trait DatabaseError: 'static + Send + Sync + StdError {
200251
/// The primary, human-readable error message.

0 commit comments

Comments
 (0)