mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 15:34:09 +00:00
feature!: added NUMERIC and DEC ANSI data types, and now the DECIMAL (#695)
type prints DECIMAL instead of NUMERIC. BREAKING CHANGE: enum DATA TYPE variants changed, changing any API that uses it.
This commit is contained in:
parent
f0646c8c1a
commit
1b3778e2d5
4 changed files with 65 additions and 31 deletions
|
@ -67,8 +67,18 @@ pub enum DataType {
|
||||||
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
|
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
|
||||||
/// [Oracle]: https://docs.oracle.com/javadb/10.8.3.0/ref/rrefblob.html
|
/// [Oracle]: https://docs.oracle.com/javadb/10.8.3.0/ref/rrefblob.html
|
||||||
Blob(Option<u64>),
|
Blob(Option<u64>),
|
||||||
/// Decimal type with optional precision and scale e.g. DECIMAL(10,2)
|
/// Numeric type with optional precision and scale e.g. NUMERIC(10,2), [standard][1]
|
||||||
|
///
|
||||||
|
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
|
||||||
|
Numeric(ExactNumberInfo),
|
||||||
|
/// Decimal type with optional precision and scale e.g. DECIMAL(10,2), [standard][1]
|
||||||
|
///
|
||||||
|
/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
|
||||||
Decimal(ExactNumberInfo),
|
Decimal(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
|
||||||
|
Dec(ExactNumberInfo),
|
||||||
/// Floating point with optional precision e.g. FLOAT(8)
|
/// Floating point with optional precision e.g. FLOAT(8)
|
||||||
Float(Option<u64>),
|
Float(Option<u64>),
|
||||||
/// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
|
/// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
|
||||||
|
@ -165,9 +175,15 @@ impl fmt::Display for DataType {
|
||||||
format_type_with_optional_length(f, "VARBINARY", size, false)
|
format_type_with_optional_length(f, "VARBINARY", size, false)
|
||||||
}
|
}
|
||||||
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
|
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
|
||||||
DataType::Decimal(info) => {
|
DataType::Numeric(info) => {
|
||||||
write!(f, "NUMERIC{}", info)
|
write!(f, "NUMERIC{}", info)
|
||||||
}
|
}
|
||||||
|
DataType::Decimal(info) => {
|
||||||
|
write!(f, "DECIMAL{}", info)
|
||||||
|
}
|
||||||
|
DataType::Dec(info) => {
|
||||||
|
write!(f, "DEC{}", info)
|
||||||
|
}
|
||||||
DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
|
DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
|
||||||
DataType::TinyInt(zerofill) => {
|
DataType::TinyInt(zerofill) => {
|
||||||
format_type_with_optional_length(f, "TINYINT", zerofill, false)
|
format_type_with_optional_length(f, "TINYINT", zerofill, false)
|
||||||
|
|
|
@ -3645,7 +3645,13 @@ impl<'a> Parser<'a> {
|
||||||
Keyword::STRING => Ok(DataType::String),
|
Keyword::STRING => Ok(DataType::String),
|
||||||
Keyword::TEXT => Ok(DataType::Text),
|
Keyword::TEXT => Ok(DataType::Text),
|
||||||
Keyword::BYTEA => Ok(DataType::Bytea),
|
Keyword::BYTEA => Ok(DataType::Bytea),
|
||||||
Keyword::NUMERIC | Keyword::DECIMAL | Keyword::DEC => Ok(DataType::Decimal(
|
Keyword::NUMERIC => Ok(DataType::Numeric(
|
||||||
|
self.parse_exact_number_optional_precision_scale()?,
|
||||||
|
)),
|
||||||
|
Keyword::DECIMAL => Ok(DataType::Decimal(
|
||||||
|
self.parse_exact_number_optional_precision_scale()?,
|
||||||
|
)),
|
||||||
|
Keyword::DEC => Ok(DataType::Dec(
|
||||||
self.parse_exact_number_optional_precision_scale()?,
|
self.parse_exact_number_optional_precision_scale()?,
|
||||||
)),
|
)),
|
||||||
Keyword::ENUM => Ok(DataType::Enum(self.parse_string_values()?)),
|
Keyword::ENUM => Ok(DataType::Enum(self.parse_string_values()?)),
|
||||||
|
@ -5784,19 +5790,47 @@ mod tests {
|
||||||
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
|
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
|
||||||
};
|
};
|
||||||
|
|
||||||
test_parse_data_type!(dialect, "NUMERIC", DataType::Decimal(ExactNumberInfo::None));
|
test_parse_data_type!(dialect, "NUMERIC", DataType::Numeric(ExactNumberInfo::None));
|
||||||
|
|
||||||
test_parse_data_type!(
|
test_parse_data_type!(
|
||||||
dialect,
|
dialect,
|
||||||
"NUMERIC(2)",
|
"NUMERIC(2)",
|
||||||
DataType::Decimal(ExactNumberInfo::Precision(2))
|
DataType::Numeric(ExactNumberInfo::Precision(2))
|
||||||
);
|
);
|
||||||
|
|
||||||
test_parse_data_type!(
|
test_parse_data_type!(
|
||||||
dialect,
|
dialect,
|
||||||
"NUMERIC(2,10)",
|
"NUMERIC(2,10)",
|
||||||
|
DataType::Numeric(ExactNumberInfo::PrecisionAndScale(2, 10))
|
||||||
|
);
|
||||||
|
|
||||||
|
test_parse_data_type!(dialect, "DECIMAL", DataType::Decimal(ExactNumberInfo::None));
|
||||||
|
|
||||||
|
test_parse_data_type!(
|
||||||
|
dialect,
|
||||||
|
"DECIMAL(2)",
|
||||||
|
DataType::Decimal(ExactNumberInfo::Precision(2))
|
||||||
|
);
|
||||||
|
|
||||||
|
test_parse_data_type!(
|
||||||
|
dialect,
|
||||||
|
"DECIMAL(2,10)",
|
||||||
DataType::Decimal(ExactNumberInfo::PrecisionAndScale(2, 10))
|
DataType::Decimal(ExactNumberInfo::PrecisionAndScale(2, 10))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_parse_data_type!(dialect, "DEC", DataType::Dec(ExactNumberInfo::None));
|
||||||
|
|
||||||
|
test_parse_data_type!(
|
||||||
|
dialect,
|
||||||
|
"DEC(2)",
|
||||||
|
DataType::Dec(ExactNumberInfo::Precision(2))
|
||||||
|
);
|
||||||
|
|
||||||
|
test_parse_data_type!(
|
||||||
|
dialect,
|
||||||
|
"DEC(2,10)",
|
||||||
|
DataType::Dec(ExactNumberInfo::PrecisionAndScale(2, 10))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -18,10 +18,8 @@
|
||||||
//! sqlparser regardless of the chosen dialect (i.e. it doesn't conflict with
|
//! sqlparser regardless of the chosen dialect (i.e. it doesn't conflict with
|
||||||
//! dialect-specific parsing rules).
|
//! dialect-specific parsing rules).
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod test_utils;
|
|
||||||
|
|
||||||
use matches::assert_matches;
|
use matches::assert_matches;
|
||||||
|
|
||||||
use sqlparser::ast::SelectItem::UnnamedExpr;
|
use sqlparser::ast::SelectItem::UnnamedExpr;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
use sqlparser::dialect::{
|
use sqlparser::dialect::{
|
||||||
|
@ -30,12 +28,14 @@ use sqlparser::dialect::{
|
||||||
};
|
};
|
||||||
use sqlparser::keywords::ALL_KEYWORDS;
|
use sqlparser::keywords::ALL_KEYWORDS;
|
||||||
use sqlparser::parser::{Parser, ParserError};
|
use sqlparser::parser::{Parser, ParserError};
|
||||||
|
|
||||||
use test_utils::{
|
use test_utils::{
|
||||||
all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias,
|
all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias,
|
||||||
TestedDialects,
|
TestedDialects,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod test_utils;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_insert_values() {
|
fn parse_insert_values() {
|
||||||
let row = vec![
|
let row = vec![
|
||||||
|
@ -1628,15 +1628,9 @@ fn parse_cast() {
|
||||||
|
|
||||||
verified_stmt("SELECT CAST(id AS NUMERIC) FROM customer");
|
verified_stmt("SELECT CAST(id AS NUMERIC) FROM customer");
|
||||||
|
|
||||||
one_statement_parses_to(
|
verified_stmt("SELECT CAST(id AS DEC) FROM customer");
|
||||||
"SELECT CAST(id AS DEC) FROM customer",
|
|
||||||
"SELECT CAST(id AS NUMERIC) FROM customer",
|
|
||||||
);
|
|
||||||
|
|
||||||
one_statement_parses_to(
|
verified_stmt("SELECT CAST(id AS DECIMAL) FROM customer");
|
||||||
"SELECT CAST(id AS DECIMAL) FROM customer",
|
|
||||||
"SELECT CAST(id AS NUMERIC) FROM customer",
|
|
||||||
);
|
|
||||||
|
|
||||||
let sql = "SELECT CAST(id AS NVARCHAR(50)) FROM customer";
|
let sql = "SELECT CAST(id AS NVARCHAR(50)) FROM customer";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
|
@ -1720,22 +1714,13 @@ fn parse_try_cast() {
|
||||||
},
|
},
|
||||||
expr_from_projection(only(&select.projection))
|
expr_from_projection(only(&select.projection))
|
||||||
);
|
);
|
||||||
one_statement_parses_to(
|
verified_stmt("SELECT TRY_CAST(id AS BIGINT) FROM customer");
|
||||||
"SELECT TRY_CAST(id AS BIGINT) FROM customer",
|
|
||||||
"SELECT TRY_CAST(id AS BIGINT) FROM customer",
|
|
||||||
);
|
|
||||||
|
|
||||||
verified_stmt("SELECT TRY_CAST(id AS NUMERIC) FROM customer");
|
verified_stmt("SELECT TRY_CAST(id AS NUMERIC) FROM customer");
|
||||||
|
|
||||||
one_statement_parses_to(
|
verified_stmt("SELECT TRY_CAST(id AS DEC) FROM customer");
|
||||||
"SELECT TRY_CAST(id AS DEC) FROM customer",
|
|
||||||
"SELECT TRY_CAST(id AS NUMERIC) FROM customer",
|
|
||||||
);
|
|
||||||
|
|
||||||
one_statement_parses_to(
|
verified_stmt("SELECT TRY_CAST(id AS DECIMAL) FROM customer");
|
||||||
"SELECT TRY_CAST(id AS DECIMAL) FROM customer",
|
|
||||||
"SELECT TRY_CAST(id AS NUMERIC) FROM customer",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -156,8 +156,7 @@ fn long_numerics() {
|
||||||
#[test]
|
#[test]
|
||||||
fn decimal_precision() {
|
fn decimal_precision() {
|
||||||
let query = "SELECT CAST(a AS DECIMAL(18,2)) FROM db.table";
|
let query = "SELECT CAST(a AS DECIMAL(18,2)) FROM db.table";
|
||||||
let expected = "SELECT CAST(a AS NUMERIC(18,2)) FROM db.table";
|
hive().verified_stmt(query);
|
||||||
hive().one_statement_parses_to(query, expected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue