From 6adc1f8b1ac578d5e614a442d24a84f09da4d318 Mon Sep 17 00:00:00 2001 From: zhongzc Date: Tue, 21 Apr 2020 14:14:56 +0800 Subject: [PATCH] cherry pick #7342 to release-3.1 Signed-off-by: zhongzc --- src/coprocessor/codec/data_type/mod.rs | 94 +++++++++++++++++++++++++- src/coprocessor/codec/mysql/decimal.rs | 5 ++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/coprocessor/codec/data_type/mod.rs b/src/coprocessor/codec/data_type/mod.rs index 859af2a2db4..0cce286e745 100644 --- a/src/coprocessor/codec/data_type/mod.rs +++ b/src/coprocessor/codec/data_type/mod.rs @@ -38,7 +38,7 @@ impl AsMySQLBool for Int { impl AsMySQLBool for Real { #[inline] fn as_mysql_bool(&self, _context: &mut EvalContext) -> Result { - Ok(self.round() != 0f64) + Ok(self.into_inner() != 0f64) } } @@ -114,3 +114,95 @@ impl_evaluable_type! { Bytes } impl_evaluable_type! { DateTime } impl_evaluable_type! { Duration } impl_evaluable_type! { Json } +<<<<<<< HEAD:src/coprocessor/codec/data_type/mod.rs +======= + +#[cfg(test)] +mod tests { + use super::*; + use std::f64; + + #[test] + fn test_bytes_as_bool() { + let tests: Vec<(&'static [u8], Option)> = vec![ + (b"", Some(false)), + (b" 23", Some(true)), + (b"-1", Some(true)), + (b"1.11", Some(true)), + (b"1.11.00", None), + (b"xx", None), + (b"0x00", None), + (b"11.xx", None), + (b"xx.11", None), + ( + b".0000000000000000000000000000000000000000000000000000001", + Some(true), + ), + ]; + + let mut ctx = EvalContext::default(); + for (i, (v, expect)) in tests.into_iter().enumerate() { + let rb: Result = v.to_vec().as_mysql_bool(&mut ctx); + match expect { + Some(val) => { + assert_eq!(rb.unwrap(), val); + } + None => { + assert!( + rb.is_err(), + "index: {}, {:?} should not be converted, but got: {:?}", + i, + v, + rb + ); + } + } + } + + // test overflow + let mut ctx = EvalContext::default(); + let val: Result = f64::INFINITY + .to_string() + .as_bytes() + .to_vec() + .as_mysql_bool(&mut ctx); + assert!(val.is_err()); + + let mut ctx = EvalContext::default(); + let val: Result = f64::NEG_INFINITY + .to_string() + .as_bytes() + .to_vec() + .as_mysql_bool(&mut ctx); + assert!(val.is_err()); + } + + #[test] + fn test_real_as_bool() { + let tests: Vec<(f64, Option)> = vec![ + (0.0, Some(false)), + (1.3, Some(true)), + (-1.234, Some(true)), + (0.000000000000000000000000000000001, Some(true)), + (-0.00000000000000000000000000000001, Some(true)), + (f64::MAX, Some(true)), + (f64::MIN, Some(true)), + (f64::MIN_POSITIVE, Some(true)), + (f64::INFINITY, Some(true)), + (f64::NEG_INFINITY, Some(true)), + (f64::NAN, None), + ]; + + let mut ctx = EvalContext::default(); + for (f, expected) in tests { + match Real::new(f) { + Ok(b) => { + let r = b.as_mysql_bool(&mut ctx).unwrap(); + assert_eq!(r, expected.unwrap()); + } + Err(_) => assert!(expected.is_none(), "{} to bool should fail", f,), + } + } + } +} +>>>>>>> 6b60d57... tidb_query: fix the logical behavior of floats (#7342):components/tidb_query_datatype/src/codec/data_type/mod.rs diff --git a/src/coprocessor/codec/mysql/decimal.rs b/src/coprocessor/codec/mysql/decimal.rs index f30fbe35c28..846fd42fd6f 100644 --- a/src/coprocessor/codec/mysql/decimal.rs +++ b/src/coprocessor/codec/mysql/decimal.rs @@ -1789,9 +1789,14 @@ impl Display for Decimal { impl crate::coprocessor::codec::data_type::AsMySQLBool for Decimal { #[inline] +<<<<<<< HEAD:src/coprocessor/codec/mysql/decimal.rs fn as_mysql_bool(&self, _context: &mut EvalContext) -> crate::coprocessor::Result { // Note: as_f64() may be never fail? Ok(self.as_f64()?.round() != 0f64) +======= + fn as_mysql_bool(&self, _ctx: &mut EvalContext) -> tidb_query_common::error::Result { + Ok(!self.is_zero()) +>>>>>>> 6b60d57... tidb_query: fix the logical behavior of floats (#7342):components/tidb_query_datatype/src/codec/mysql/decimal.rs } }