Skip to content

Commit f5f51eb

Browse files
authored
MySQL: Allow optional SIGNED suffix on integer data types (#1985)
1 parent 3d2db8c commit f5f51eb

File tree

5 files changed

+83
-0
lines changed

5 files changed

+83
-0
lines changed

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,8 @@ impl Dialect for GenericDialect {
183183
fn supports_select_wildcard_exclude(&self) -> bool {
184184
true
185185
}
186+
187+
fn supports_data_type_signed_suffix(&self) -> bool {
188+
true
189+
}
186190
}

src/dialect/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,18 @@ pub trait Dialect: Debug + Any {
11361136
fn supports_notnull_operator(&self) -> bool {
11371137
false
11381138
}
1139+
1140+
/// Returns true if this dialect allows an optional `SIGNED` suffix after integer data types.
1141+
///
1142+
/// Example:
1143+
/// ```sql
1144+
/// CREATE TABLE t (i INT(20) SIGNED);
1145+
/// ```
1146+
///
1147+
/// Note that this is canonicalized to `INT(20)`.
1148+
fn supports_data_type_signed_suffix(&self) -> bool {
1149+
false
1150+
}
11391151
}
11401152

11411153
/// This represents the operators for which precedence must be defined

src/dialect/mysql.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ impl Dialect for MySqlDialect {
154154
fn supports_comma_separated_set_assignments(&self) -> bool {
155155
true
156156
}
157+
158+
fn supports_data_type_signed_suffix(&self) -> bool {
159+
true
160+
}
157161
}
158162

159163
/// `LOCK TABLES`

src/parser/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9848,6 +9848,9 @@ impl<'a> Parser<'a> {
98489848
if self.parse_keyword(Keyword::UNSIGNED) {
98499849
Ok(DataType::TinyIntUnsigned(optional_precision?))
98509850
} else {
9851+
if dialect.supports_data_type_signed_suffix() {
9852+
let _ = self.parse_keyword(Keyword::SIGNED);
9853+
}
98519854
Ok(DataType::TinyInt(optional_precision?))
98529855
}
98539856
}
@@ -9864,6 +9867,9 @@ impl<'a> Parser<'a> {
98649867
if self.parse_keyword(Keyword::UNSIGNED) {
98659868
Ok(DataType::SmallIntUnsigned(optional_precision?))
98669869
} else {
9870+
if dialect.supports_data_type_signed_suffix() {
9871+
let _ = self.parse_keyword(Keyword::SIGNED);
9872+
}
98679873
Ok(DataType::SmallInt(optional_precision?))
98689874
}
98699875
}
@@ -9872,6 +9878,9 @@ impl<'a> Parser<'a> {
98729878
if self.parse_keyword(Keyword::UNSIGNED) {
98739879
Ok(DataType::MediumIntUnsigned(optional_precision?))
98749880
} else {
9881+
if dialect.supports_data_type_signed_suffix() {
9882+
let _ = self.parse_keyword(Keyword::SIGNED);
9883+
}
98759884
Ok(DataType::MediumInt(optional_precision?))
98769885
}
98779886
}
@@ -9880,6 +9889,9 @@ impl<'a> Parser<'a> {
98809889
if self.parse_keyword(Keyword::UNSIGNED) {
98819890
Ok(DataType::IntUnsigned(optional_precision?))
98829891
} else {
9892+
if dialect.supports_data_type_signed_suffix() {
9893+
let _ = self.parse_keyword(Keyword::SIGNED);
9894+
}
98839895
Ok(DataType::Int(optional_precision?))
98849896
}
98859897
}
@@ -9909,6 +9921,9 @@ impl<'a> Parser<'a> {
99099921
if self.parse_keyword(Keyword::UNSIGNED) {
99109922
Ok(DataType::IntegerUnsigned(optional_precision?))
99119923
} else {
9924+
if dialect.supports_data_type_signed_suffix() {
9925+
let _ = self.parse_keyword(Keyword::SIGNED);
9926+
}
99129927
Ok(DataType::Integer(optional_precision?))
99139928
}
99149929
}
@@ -9917,6 +9932,9 @@ impl<'a> Parser<'a> {
99179932
if self.parse_keyword(Keyword::UNSIGNED) {
99189933
Ok(DataType::BigIntUnsigned(optional_precision?))
99199934
} else {
9935+
if dialect.supports_data_type_signed_suffix() {
9936+
let _ = self.parse_keyword(Keyword::SIGNED);
9937+
}
99209938
Ok(DataType::BigInt(optional_precision?))
99219939
}
99229940
}

tests/sqlparser_mysql.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,51 @@ fn parse_create_table_unsigned() {
17051705
}
17061706
}
17071707

1708+
#[test]
1709+
fn parse_signed_data_types() {
1710+
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)";
1711+
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))";
1712+
match mysql().one_statement_parses_to(sql, canonical) {
1713+
Statement::CreateTable(CreateTable { name, columns, .. }) => {
1714+
assert_eq!(name.to_string(), "foo");
1715+
assert_eq!(
1716+
vec![
1717+
ColumnDef {
1718+
name: Ident::new("bar_tinyint"),
1719+
data_type: DataType::TinyInt(Some(3)),
1720+
options: vec![],
1721+
},
1722+
ColumnDef {
1723+
name: Ident::new("bar_smallint"),
1724+
data_type: DataType::SmallInt(Some(5)),
1725+
options: vec![],
1726+
},
1727+
ColumnDef {
1728+
name: Ident::new("bar_mediumint"),
1729+
data_type: DataType::MediumInt(Some(13)),
1730+
options: vec![],
1731+
},
1732+
ColumnDef {
1733+
name: Ident::new("bar_int"),
1734+
data_type: DataType::Int(Some(11)),
1735+
options: vec![],
1736+
},
1737+
ColumnDef {
1738+
name: Ident::new("bar_bigint"),
1739+
data_type: DataType::BigInt(Some(20)),
1740+
options: vec![],
1741+
},
1742+
],
1743+
columns
1744+
);
1745+
}
1746+
_ => unreachable!(),
1747+
}
1748+
all_dialects_except(|d| d.supports_data_type_signed_suffix())
1749+
.run_parser_method(sql, |p| p.parse_statement())
1750+
.expect_err("SIGNED suffix should not be allowed");
1751+
}
1752+
17081753
#[test]
17091754
fn parse_simple_insert() {
17101755
let sql = r"INSERT INTO tasks (title, priority) VALUES ('Test Some Inserts', 1), ('Test Entry 2', 2), ('Test Entry 3', 3)";

0 commit comments

Comments
 (0)