From fbbf1a4e848bcaed8740854e91ce9e4481b2c115 Mon Sep 17 00:00:00 2001 From: Y Togami <62130798+togami2864@users.noreply.github.com> Date: Fri, 3 Mar 2023 00:38:00 +0900 Subject: [PATCH] feat: support `BIGNUMERIC` of bigquery (#811) * add tests * bignumeric data type * bignumeric keyword * fix doc * add exact_number_info * fix doc * check result string --- src/ast/data_type.rs | 10 ++++++ src/keywords.rs | 2 ++ src/parser.rs | 6 ++++ tests/sqlparser_common.rs | 69 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index bd1c468e..647e7b35 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -79,6 +79,14 @@ pub enum DataType { /// /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type Decimal(ExactNumberInfo), + /// [BigNumeric] type used in BigQuery + /// + /// [BigNumeric]: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#bignumeric_literals + BigNumeric(ExactNumberInfo), + /// This is alias for `BigNumeric` type used in BigQuery + /// + /// [BigDecimal]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#decimal_types + BigDecimal(ExactNumberInfo), /// Dec type with optional precision and scale e.g. DEC(10,2), [standard][1] /// /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type @@ -196,6 +204,8 @@ impl fmt::Display for DataType { DataType::Dec(info) => { write!(f, "DEC{info}") } + DataType::BigNumeric(info) => write!(f, "BIGNUMERIC{info}"), + DataType::BigDecimal(info) => write!(f, "BIGDECIMAL{info}"), DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false), DataType::TinyInt(zerofill) => { format_type_with_optional_length(f, "TINYINT", zerofill, false) diff --git a/src/keywords.rs b/src/keywords.rs index 18338ccd..af741aee 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -104,7 +104,9 @@ define_keywords!( BEGIN_FRAME, BEGIN_PARTITION, BETWEEN, + BIGDECIMAL, BIGINT, + BIGNUMERIC, BINARY, BLOB, BOOLEAN, diff --git a/src/parser.rs b/src/parser.rs index e7731e2a..dbbad7f0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4432,6 +4432,12 @@ impl<'a> Parser<'a> { Keyword::DEC => Ok(DataType::Dec( self.parse_exact_number_optional_precision_scale()?, )), + Keyword::BIGNUMERIC => Ok(DataType::BigNumeric( + self.parse_exact_number_optional_precision_scale()?, + )), + Keyword::BIGDECIMAL => Ok(DataType::BigDecimal( + self.parse_exact_number_optional_precision_scale()?, + )), Keyword::ENUM => Ok(DataType::Enum(self.parse_string_values()?)), Keyword::SET => Ok(DataType::Set(self.parse_string_values()?)), Keyword::ARRAY => { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index faab5049..0d91aac0 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3658,6 +3658,75 @@ fn parse_json_keyword() { ); } +#[test] +fn parse_bignumeric_keyword() { + let sql = r#"SELECT BIGNUMERIC '0'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"0"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '0'"); + + let sql = r#"SELECT BIGNUMERIC '123456'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"123456"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '123456'"); + + let sql = r#"SELECT BIGNUMERIC '-3.14'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"-3.14"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '-3.14'"); + + let sql = r#"SELECT BIGNUMERIC '-0.54321'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"-0.54321"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '-0.54321'"); + + let sql = r#"SELECT BIGNUMERIC '1.23456e05'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"1.23456e05"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '1.23456e05'"); + + let sql = r#"SELECT BIGNUMERIC '-9.876e-3'"#; + let select = verified_only_select(sql); + assert_eq!( + &Expr::TypedString { + data_type: DataType::BigNumeric(ExactNumberInfo::None), + value: r#"-9.876e-3"#.into() + }, + expr_from_projection(only(&select.projection)), + ); + verified_stmt("SELECT BIGNUMERIC '-9.876e-3'"); +} + #[test] fn parse_simple_math_expr_plus() { let sql = "SELECT a + b, 2 + a, 2.5 + a, a_f + b_f, 2 + a_f, 2.5 + a_f FROM c";