From e767f372417e99f44d9fe08eef55e65c55c505f3 Mon Sep 17 00:00:00 2001 From: Weny Xu Date: Mon, 11 Mar 2024 17:28:40 +0800 Subject: [PATCH] fix: fix f64 has no sufficient precision during parsing (#3483) --- Cargo.toml | 2 +- src/datatypes/src/value.rs | 8 +++++++ src/sql/src/parsers/create_parser.rs | 21 +++++++++++++++++ src/sql/src/statements.rs | 23 +++++++++++++++++++ .../standalone/common/create/create.result | 21 +++++++++++++++++ .../cases/standalone/common/create/create.sql | 10 ++++++++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 83fd64c6778e..c1604c1ff997 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -134,7 +134,7 @@ reqwest = { version = "0.11", default-features = false, features = [ rskafka = "0.5" rust_decimal = "1.33" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde_json = { version = "1.0", features = ["float_roundtrip"] } serde_with = "3" smallvec = { version = "1", features = ["serde"] } snafu = "0.7" diff --git a/src/datatypes/src/value.rs b/src/datatypes/src/value.rs index bfd4a11103e4..64635eeae2d0 100644 --- a/src/datatypes/src/value.rs +++ b/src/datatypes/src/value.rs @@ -2417,4 +2417,12 @@ mod tests { ); check_value_ref_size_eq(&ValueRef::Decimal128(Decimal128::new(1234, 3, 1)), 32) } + + #[test] + fn test_incorrect_default_value_issue_3479() { + let value = OrderedF64::from(0.047318541668048164); + let serialized = serde_json::to_string(&value).unwrap(); + let deserialized: OrderedF64 = serde_json::from_str(&serialized).unwrap(); + assert_eq!(value, deserialized); + } } diff --git a/src/sql/src/parsers/create_parser.rs b/src/sql/src/parsers/create_parser.rs index 00a797d44b23..606ee3ebef08 100644 --- a/src/sql/src/parsers/create_parser.rs +++ b/src/sql/src/parsers/create_parser.rs @@ -1495,4 +1495,25 @@ ENGINE=mito"; ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default()); let _ = result.unwrap(); } + + #[test] + fn test_incorrect_default_value_issue_3479() { + let sql = r#"CREATE TABLE `ExcePTuRi`( +non TIMESTAMP(6) TIME INDEX, +`iUSTO` DOUBLE DEFAULT 0.047318541668048164 +)"#; + let result = + ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default()) + .unwrap(); + assert_eq!(1, result.len()); + match &result[0] { + Statement::CreateTable(c) => { + assert_eq!( + "`iUSTO` DOUBLE DEFAULT 0.047318541668048164", + c.columns[1].to_string() + ); + } + _ => unreachable!(), + } + } } diff --git a/src/sql/src/statements.rs b/src/sql/src/statements.rs index a8f38e545d59..d51378c0982f 100644 --- a/src/sql/src/statements.rs +++ b/src/sql/src/statements.rs @@ -904,6 +904,29 @@ mod tests { ); } + #[test] + fn test_incorrect_default_value_issue_3479() { + let opts = vec![ColumnOptionDef { + name: None, + option: ColumnOption::Default(Expr::Value(SqlValue::Number( + "0.047318541668048164".into(), + false, + ))), + }]; + let constraint = parse_column_default_constraint( + "coll", + &ConcreteDataType::float64_datatype(), + &opts, + None, + ) + .unwrap() + .unwrap(); + assert_eq!("0.047318541668048164", constraint.to_string()); + let encoded: Vec = constraint.clone().try_into().unwrap(); + let decoded = ColumnDefaultConstraint::try_from(encoded.as_ref()).unwrap(); + assert_eq!(decoded, constraint); + } + #[test] pub fn test_sql_column_def_to_grpc_column_def() { // test basic diff --git a/tests/cases/standalone/common/create/create.result b/tests/cases/standalone/common/create/create.result index 664c94fedebc..ed0529b9345e 100644 --- a/tests/cases/standalone/common/create/create.result +++ b/tests/cases/standalone/common/create/create.result @@ -155,6 +155,23 @@ CREATE TABLE test_like_2 LIKE test_like_1; Error: 4000(TableAlreadyExists), Table already exists: `greptime.public.test_like_2` +CREATE TABLE `ExcePTuRi`( +non TIMESTAMP(6) TIME INDEX, +`iUSTO` DOUBLE DEFAULT 0.047318541668048164 +) +ENGINE=mito; + +Affected Rows: 0 + +DESC table `ExcePTuRi`; + ++--------+----------------------+-----+------+----------------------+---------------+ +| Column | Type | Key | Null | Default | Semantic Type | ++--------+----------------------+-----+------+----------------------+---------------+ +| non | TimestampMicrosecond | PRI | NO | | TIMESTAMP | +| iUSTO | Float64 | | YES | 0.047318541668048164 | FIELD | ++--------+----------------------+-----+------+----------------------+---------------+ + DESC TABLE test_like_1; +--------+----------------------+-----+------+---------+---------------+ @@ -183,3 +200,7 @@ DROP TABLE test_like_2; Affected Rows: 0 +DROP table `ExcePTuRi`; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/create/create.sql b/tests/cases/standalone/common/create/create.sql index f27b2bc6e812..9f541da3126e 100644 --- a/tests/cases/standalone/common/create/create.sql +++ b/tests/cases/standalone/common/create/create.sql @@ -64,6 +64,14 @@ CREATE TABLE test_like_2 LIKE test_like_1; CREATE TABLE test_like_2 LIKE test_like_1; +CREATE TABLE `ExcePTuRi`( +non TIMESTAMP(6) TIME INDEX, +`iUSTO` DOUBLE DEFAULT 0.047318541668048164 +) +ENGINE=mito; + +DESC table `ExcePTuRi`; + DESC TABLE test_like_1; DESC TABLE test_like_2; @@ -71,3 +79,5 @@ DESC TABLE test_like_2; DROP TABLE test_like_1; DROP TABLE test_like_2; + +DROP table `ExcePTuRi`;