-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Open
Labels
Description
I have found these related issues/pull requests
During the conversion of MySqlRow to AnyRow, sqlx unexpectedly treated the binary(size) type as a string, which caused the utf8 decoding to fail.
Description
In code:
Lines 152 to 179 in e8384f2
| impl<'a> TryFrom<&'a MySqlTypeInfo> for AnyTypeInfo { | |
| type Error = sqlx_core::Error; | |
| fn try_from(type_info: &'a MySqlTypeInfo) -> Result<Self, Self::Error> { | |
| Ok(AnyTypeInfo { | |
| kind: match &type_info.r#type { | |
| ColumnType::Null => AnyTypeInfoKind::Null, | |
| ColumnType::Short => AnyTypeInfoKind::SmallInt, | |
| ColumnType::Long => AnyTypeInfoKind::Integer, | |
| ColumnType::LongLong => AnyTypeInfoKind::BigInt, | |
| ColumnType::Float => AnyTypeInfoKind::Real, | |
| ColumnType::Double => AnyTypeInfoKind::Double, | |
| ColumnType::Blob | |
| | ColumnType::TinyBlob | |
| | ColumnType::MediumBlob | |
| | ColumnType::LongBlob => AnyTypeInfoKind::Blob, | |
| ColumnType::String | ColumnType::VarString | ColumnType::VarChar => { | |
| AnyTypeInfoKind::Text | |
| } | |
| _ => { | |
| return Err(sqlx_core::Error::AnyDriverError( | |
| format!("Any driver does not support MySql type {type_info:?}").into(), | |
| )) | |
| } | |
| }, | |
| }) | |
| } | |
| } |
MySqlTypeInfo has type = ColumnType::String and flags = 4227, this value should be treated as binary data, but it actual be treated as string.
After apply this patch, everything work fine:
diff --git a/sqlx-mysql/src/any.rs b/sqlx-mysql/src/any.rs
index 19b3a6f2..a247499e 100644
--- a/sqlx-mysql/src/any.rs
+++ b/sqlx-mysql/src/any.rs
@@ -1,4 +1,4 @@
-use crate::protocol::text::ColumnType;
+use crate::protocol::text::{ColumnFlags, ColumnType};
use crate::{
MySql, MySqlColumn, MySqlConnectOptions, MySqlConnection, MySqlQueryResult, MySqlRow,
MySqlTransactionManager, MySqlTypeInfo,
@@ -173,7 +173,11 @@ impl<'a> TryFrom<&'a MySqlTypeInfo> for AnyTypeInfo {
| ColumnType::MediumBlob
| ColumnType::LongBlob => AnyTypeInfoKind::Blob,
ColumnType::String | ColumnType::VarString | ColumnType::VarChar => {
- AnyTypeInfoKind::Text
+ if type_info.flags.contains(ColumnFlags::BINARY) {
+ AnyTypeInfoKind::Blob
+ } else {
+ AnyTypeInfoKind::Text
+ }
}
_ => {
return Err(sqlx_core::Error::AnyDriverError(Reproduction steps
Run follow code:
#[tokio::main]
async fn main() {
sqlx::any::install_default_drivers();
let pool = sqlx::AnyPool::connect(env!("DATABASE_URL")).await.unwrap();
sqlx::query("CREATE TABLE IF NOT EXISTS `test`(id BINARY(16) PRIMARY KEY)")
.execute(&pool)
.await
.unwrap();
sqlx::query("INSERT INTO `test`(id) VALUES(UNHEX(REPLACE(UUID(), '-', '')))")
.execute(&pool)
.await
.unwrap();
sqlx::query("SELECT * FROM `test`").fetch_all(&pool).await.unwrap(); // panic: called `Result::unwrap()` on an `Err` value: Decode(Utf8Error { valid_up_to: 4, error_len: Some(1) })
}It panic with Utf8Error:
thread 'main' (298286) panicked at src/main.rs:17:64:
called `Result::unwrap()` on an `Err` value: Decode(Utf8Error { valid_up_to: 4, error_len: Some(1) })
SQLx version
0.8.6
Enabled SQLx features
["runtime-tokio", "mysql", "macros", "any"]
Database server and version
/usr/sbin/mysqld Ver 9.5.0 for Linux on x86_64 (MySQL Community Server - GPL)
Operating system
Linux 6.18.2-arch2-1 #1 SMP PREEMPT_DYNAMIC Thu, 18 Dec 2025 18:00:18 +0000 x86_64 GNU/Linux
Rust version
rustc 1.91.1 (ed61e7d7e 2025-11-07)