From 4175d681d9e002af8f8326392ed27418b73363e0 Mon Sep 17 00:00:00 2001 From: zhongzc Date: Mon, 20 Apr 2020 11:15:17 +0800 Subject: [PATCH] tidb_query: fix converting bytes to bool (#7486) Signed-off-by: zhongzc --- .../src/codec/data_type/mod.rs | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/components/tidb_query_datatype/src/codec/data_type/mod.rs b/components/tidb_query_datatype/src/codec/data_type/mod.rs index fcdbcf2a78e..944aec63123 100644 --- a/components/tidb_query_datatype/src/codec/data_type/mod.rs +++ b/components/tidb_query_datatype/src/codec/data_type/mod.rs @@ -13,9 +13,9 @@ pub use crate::codec::mysql::{Decimal, Duration, Json, JsonType, Time as DateTim pub use self::scalar::{ScalarValue, ScalarValueRef}; pub use self::vector::{VectorValue, VectorValueExt}; -use crate::{EvalType, FieldTypeTp}; +use crate::EvalType; -use crate::codec::convert::ToInt; +use crate::codec::convert::ConvertTo; use crate::expr::EvalContext; use tidb_query_common::error::Result; @@ -43,7 +43,7 @@ impl AsMySQLBool for Real { impl AsMySQLBool for Bytes { #[inline] fn as_mysql_bool(&self, context: &mut EvalContext) -> Result { - Ok(!self.is_empty() && self.to_int(context, FieldTypeTp::LongLong)? != 0) + Ok(!self.is_empty() && ConvertTo::::convert(self, context)? != 0f64) } } @@ -122,3 +122,64 @@ impl_evaluable_type! { Bytes } impl_evaluable_type! { DateTime } impl_evaluable_type! { Duration } impl_evaluable_type! { Json } + +#[cfg(test)] +mod tests { + use super::*; + use std::f64; + + #[test] + fn test_bytes_to_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()); + } +}