Skip to content

Commit 83baf5e

Browse files
mvzinkyoavcloud
andauthored
Support MySQL KEY keyword in column definitions (#2243)
Co-authored-by: Yoav Cohen <59807311+yoavcloud@users.noreply.github.com>
1 parent 6f0e803 commit 83baf5e

File tree

6 files changed

+53
-2
lines changed

6 files changed

+53
-2
lines changed

src/ast/ddl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,7 @@ impl fmt::Display for ColumnOption {
20402040
Ok(())
20412041
}
20422042
Unique(constraint) => {
2043-
write!(f, "UNIQUE")?;
2043+
write!(f, "UNIQUE{:>}", constraint.index_type_display)?;
20442044
if let Some(characteristics) = &constraint.characteristics {
20452045
write!(f, " {characteristics}")?;
20462046
}

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,8 @@ impl Dialect for GenericDialect {
280280
fn supports_constraint_keyword_without_name(&self) -> bool {
281281
true
282282
}
283+
284+
fn supports_key_column_option(&self) -> bool {
285+
true
286+
}
283287
}

src/dialect/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,18 @@ pub trait Dialect: Debug + Any {
11951195
false
11961196
}
11971197

1198+
/// Returns true if the dialect supports the `KEY` keyword as part of
1199+
/// column-level constraints in a `CREATE TABLE` statement.
1200+
///
1201+
/// When enabled, the parser accepts these MySQL-specific column options:
1202+
/// - `UNIQUE [KEY]` — optional `KEY` after `UNIQUE`
1203+
/// - `[PRIMARY] KEY` — standalone `KEY` as shorthand for `PRIMARY KEY`
1204+
///
1205+
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
1206+
fn supports_key_column_option(&self) -> bool {
1207+
false
1208+
}
1209+
11981210
/// Returns true if the specified keyword is reserved and cannot be
11991211
/// used as an identifier without special handling like quoting.
12001212
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {

src/dialect/mysql.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ impl Dialect for MySqlDialect {
206206
fn supports_constraint_keyword_without_name(&self) -> bool {
207207
true
208208
}
209+
210+
/// See: <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
211+
fn supports_key_column_option(&self) -> bool {
212+
true
213+
}
209214
}
210215

211216
/// `LOCK TABLES`

src/parser/mod.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9048,12 +9048,18 @@ impl<'a> Parser<'a> {
90489048
.into(),
90499049
))
90509050
} else if self.parse_keyword(Keyword::UNIQUE) {
9051+
let index_type_display =
9052+
if self.dialect.supports_key_column_option() && self.parse_keyword(Keyword::KEY) {
9053+
KeyOrIndexDisplay::Key
9054+
} else {
9055+
KeyOrIndexDisplay::None
9056+
};
90519057
let characteristics = self.parse_constraint_characteristics()?;
90529058
Ok(Some(
90539059
UniqueConstraint {
90549060
name: None,
90559061
index_name: None,
9056-
index_type_display: KeyOrIndexDisplay::None,
9062+
index_type_display,
90579063
index_type: None,
90589064
columns: vec![],
90599065
index_options: vec![],
@@ -9062,6 +9068,21 @@ impl<'a> Parser<'a> {
90629068
}
90639069
.into(),
90649070
))
9071+
} else if self.dialect.supports_key_column_option() && self.parse_keyword(Keyword::KEY) {
9072+
// In MySQL, `KEY` in a column definition is shorthand for `PRIMARY KEY`.
9073+
// See: https://dev.mysql.com/doc/refman/8.4/en/create-table.html
9074+
let characteristics = self.parse_constraint_characteristics()?;
9075+
Ok(Some(
9076+
PrimaryKeyConstraint {
9077+
name: None,
9078+
index_name: None,
9079+
index_type: None,
9080+
columns: vec![],
9081+
index_options: vec![],
9082+
characteristics,
9083+
}
9084+
.into(),
9085+
))
90659086
} else if self.parse_keyword(Keyword::REFERENCES) {
90669087
let foreign_table = self.parse_object_name(false)?;
90679088
// PostgreSQL allows omitting the column list and

tests/sqlparser_mysql.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,15 @@ fn parse_create_table_primary_and_unique_key_characteristic_test() {
944944
}
945945
}
946946

947+
#[test]
948+
fn parse_create_table_column_key_options() {
949+
mysql_and_generic().verified_stmt("CREATE TABLE foo (x INT UNIQUE KEY)");
950+
mysql_and_generic().one_statement_parses_to(
951+
"CREATE TABLE foo (x INT KEY)",
952+
"CREATE TABLE foo (x INT PRIMARY KEY)",
953+
);
954+
}
955+
947956
#[test]
948957
fn parse_create_table_comment() {
949958
let without_equal = "CREATE TABLE foo (bar INT) COMMENT 'baz'";

0 commit comments

Comments
 (0)