mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-02-15 04:09:37 +00:00
Merge pull request #101 from launchbadge/ab/mysql-floats
fix and test floats in MySQL
This commit is contained in:
commit
97eec46a3b
@ -104,8 +104,8 @@ impl Row {
|
||||
let size = match columns[column_idx] {
|
||||
TypeId::TINY_INT => 1,
|
||||
TypeId::SMALL_INT => 2,
|
||||
TypeId::INT => 4,
|
||||
TypeId::BIG_INT => 8,
|
||||
TypeId::INT | TypeId::FLOAT => 4,
|
||||
TypeId::BIG_INT | TypeId::DOUBLE => 8,
|
||||
|
||||
TypeId::DATE => 5,
|
||||
TypeId::TIME => 1 + buffer[index] as usize,
|
||||
|
||||
@ -5,6 +5,19 @@ use crate::mysql::types::MySqlTypeInfo;
|
||||
use crate::mysql::MySql;
|
||||
use crate::types::HasSqlType;
|
||||
|
||||
/// The equivalent MySQL type for `f32` is `FLOAT`.
|
||||
///
|
||||
/// ### Note
|
||||
/// While we added support for `f32` as `FLOAT` for completeness, we don't recommend using
|
||||
/// it for any real-life applications as it cannot precisely represent some fractional values,
|
||||
/// and may be implicitly widened to `DOUBLE` in some cases, resulting in a slightly different
|
||||
/// value:
|
||||
///
|
||||
/// ```rust
|
||||
/// // Widening changes the equivalent decimal value, these two expressions are not equal
|
||||
/// // (This is expected behavior for floating points and happens both in Rust and in MySQL)
|
||||
/// assert_ne!(10.2f32 as f64, 10.2f64);
|
||||
/// ```
|
||||
impl HasSqlType<f32> for MySql {
|
||||
fn type_info() -> MySqlTypeInfo {
|
||||
MySqlTypeInfo::new(TypeId::FLOAT)
|
||||
@ -23,6 +36,10 @@ impl Decode<MySql> for f32 {
|
||||
}
|
||||
}
|
||||
|
||||
/// The equivalent MySQL type for `f64` is `DOUBLE`.
|
||||
///
|
||||
/// Note that `DOUBLE` is a floating-point type and cannot represent some fractional values
|
||||
/// exactly.
|
||||
impl HasSqlType<f64> for MySql {
|
||||
fn type_info() -> MySqlTypeInfo {
|
||||
MySqlTypeInfo::new(TypeId::DOUBLE)
|
||||
|
||||
@ -18,11 +18,11 @@ macro_rules! test {
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert_eq!(row.get::<i32, _>(0), 1);
|
||||
|
||||
let value = row.get::<$ty, _>("_1");
|
||||
|
||||
assert!($value == value);
|
||||
assert_eq!(row.get::<i32, _>(0), 1, "value returned from server: {:?}", value);
|
||||
|
||||
assert_eq!($value, value);
|
||||
)+
|
||||
|
||||
Ok(())
|
||||
@ -44,6 +44,9 @@ test!(mysql_long: i32: "2141512" == 2141512_i32);
|
||||
test!(mysql_longlong_unsigned: u64: "2141512" == 2141512_u64);
|
||||
test!(mysql_longlong: i64: "2141512" == 2141512_i64);
|
||||
|
||||
// `DOUBLE` can be compared with decimal literals just fine but the same can't be said for `FLOAT`
|
||||
test!(mysql_double: f64: "3.14159265" == 3.14159265f64);
|
||||
|
||||
test!(mysql_string: String: "'helloworld'" == "helloworld");
|
||||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
@ -69,3 +72,23 @@ async fn mysql_bytes() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
|
||||
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
|
||||
async fn mysql_float() -> anyhow::Result<()> {
|
||||
let mut conn = connect().await?;
|
||||
|
||||
let value = 10.2f32;
|
||||
let row = sqlx::query("SELECT ? as _1")
|
||||
.bind(value)
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
// comparison between FLOAT and literal doesn't work as expected
|
||||
// we get implicit widening to DOUBLE which gives a slightly different value
|
||||
// however, round-trip does work as expected
|
||||
let ret = row.get::<f32, _>("_1");
|
||||
assert_eq!(value, ret);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user