mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-24 16:04:04 +00:00
MySQL: Allow optional SIGNED
suffix on integer data types
In MySQL, a data type like `INT(20) SIGNED` is equivalent to `INT(20)`. In other dialects, this may be interpreted differently; e.g. in Postgres, `SELECT 1::integer signed` indicates an alias of "signed". So we parse the optional `SIGNED` suffix only on dialects that allow it (I currently don't know of any other than MySQL).
This commit is contained in:
parent
3d2db8c69b
commit
28d2183ff3
5 changed files with 83 additions and 0 deletions
|
@ -183,4 +183,8 @@ impl Dialect for GenericDialect {
|
|||
fn supports_select_wildcard_exclude(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_data_type_signed_suffix(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1136,6 +1136,18 @@ pub trait Dialect: Debug + Any {
|
|||
fn supports_notnull_operator(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if this dialect allows an optional `SIGNED` suffix after integer data types.
|
||||
///
|
||||
/// Example:
|
||||
/// ```sql
|
||||
/// CREATE TABLE t (i INT(20) SIGNED);
|
||||
/// ```
|
||||
///
|
||||
/// Note that this is canonicalized to `INT(20)`.
|
||||
fn supports_data_type_signed_suffix(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// This represents the operators for which precedence must be defined
|
||||
|
|
|
@ -154,6 +154,10 @@ impl Dialect for MySqlDialect {
|
|||
fn supports_comma_separated_set_assignments(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_data_type_signed_suffix(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// `LOCK TABLES`
|
||||
|
|
|
@ -9848,6 +9848,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::TinyIntUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::TinyInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
@ -9864,6 +9867,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::SmallIntUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::SmallInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
@ -9872,6 +9878,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::MediumIntUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::MediumInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
@ -9880,6 +9889,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::IntUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::Int(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
@ -9909,6 +9921,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::IntegerUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::Integer(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
@ -9917,6 +9932,9 @@ impl<'a> Parser<'a> {
|
|||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::BigIntUnsigned(optional_precision?))
|
||||
} else {
|
||||
if dialect.supports_data_type_signed_suffix() {
|
||||
let _ = self.parse_keyword(Keyword::SIGNED);
|
||||
}
|
||||
Ok(DataType::BigInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1705,6 +1705,51 @@ fn parse_create_table_unsigned() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_signed_data_types() {
|
||||
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3) SIGNED, bar_smallint SMALLINT(5) SIGNED, bar_mediumint MEDIUMINT(13) SIGNED, bar_int INT(11) SIGNED, bar_bigint BIGINT(20) SIGNED)";
|
||||
let canonical = "CREATE TABLE foo (bar_tinyint TINYINT(3), bar_smallint SMALLINT(5), bar_mediumint MEDIUMINT(13), bar_int INT(11), bar_bigint BIGINT(20))";
|
||||
match mysql().one_statement_parses_to(sql, canonical) {
|
||||
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
assert_eq!(
|
||||
vec![
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_tinyint"),
|
||||
data_type: DataType::TinyInt(Some(3)),
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_smallint"),
|
||||
data_type: DataType::SmallInt(Some(5)),
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_mediumint"),
|
||||
data_type: DataType::MediumInt(Some(13)),
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_int"),
|
||||
data_type: DataType::Int(Some(11)),
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_bigint"),
|
||||
data_type: DataType::BigInt(Some(20)),
|
||||
options: vec![],
|
||||
},
|
||||
],
|
||||
columns
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
all_dialects_except(|d| d.supports_data_type_signed_suffix())
|
||||
.run_parser_method(sql, |p| p.parse_statement())
|
||||
.expect_err("SIGNED suffix should not be allowed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_simple_insert() {
|
||||
let sql = r"INSERT INTO tasks (title, priority) VALUES ('Test Some Inserts', 1), ('Test Entry 2', 2), ('Test Entry 3', 3)";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue