Skip to content

Commit de2cc7b

Browse files
MySQL: Support index_name in FK constraints (#1871)
1 parent 5327f0c commit de2cc7b

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

src/ast/ddl.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,9 @@ pub enum TableConstraint {
10191019
/// }`).
10201020
ForeignKey {
10211021
name: Option<Ident>,
1022+
/// MySQL-specific field
1023+
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html>
1024+
index_name: Option<Ident>,
10221025
columns: Vec<Ident>,
10231026
foreign_table: ObjectName,
10241027
referred_columns: Vec<Ident>,
@@ -1129,6 +1132,7 @@ impl fmt::Display for TableConstraint {
11291132
}
11301133
TableConstraint::ForeignKey {
11311134
name,
1135+
index_name,
11321136
columns,
11331137
foreign_table,
11341138
referred_columns,
@@ -1138,8 +1142,9 @@ impl fmt::Display for TableConstraint {
11381142
} => {
11391143
write!(
11401144
f,
1141-
"{}FOREIGN KEY ({}) REFERENCES {}",
1145+
"{}FOREIGN KEY{} ({}) REFERENCES {}",
11421146
display_constraint_name(name),
1147+
display_option_spaced(index_name),
11431148
display_comma_separated(columns),
11441149
foreign_table,
11451150
)?;

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ impl Spanned for TableConstraint {
671671
TableConstraint::ForeignKey {
672672
name,
673673
columns,
674+
index_name,
674675
foreign_table,
675676
referred_columns,
676677
on_delete,
@@ -679,6 +680,7 @@ impl Spanned for TableConstraint {
679680
} => union_spans(
680681
name.iter()
681682
.map(|i| i.span)
683+
.chain(index_name.iter().map(|i| i.span))
682684
.chain(columns.iter().map(|i| i.span))
683685
.chain(core::iter::once(foreign_table.span()))
684686
.chain(referred_columns.iter().map(|i| i.span))

src/parser/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8061,7 +8061,7 @@ impl<'a> Parser<'a> {
80618061
let nulls_distinct = self.parse_optional_nulls_distinct()?;
80628062

80638063
// optional index name
8064-
let index_name = self.parse_optional_indent()?;
8064+
let index_name = self.parse_optional_ident()?;
80658065
let index_type = self.parse_optional_using_then_index_type()?;
80668066

80678067
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
@@ -8083,7 +8083,7 @@ impl<'a> Parser<'a> {
80838083
self.expect_keyword_is(Keyword::KEY)?;
80848084

80858085
// optional index name
8086-
let index_name = self.parse_optional_indent()?;
8086+
let index_name = self.parse_optional_ident()?;
80878087
let index_type = self.parse_optional_using_then_index_type()?;
80888088

80898089
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
@@ -8100,6 +8100,7 @@ impl<'a> Parser<'a> {
81008100
}
81018101
Token::Word(w) if w.keyword == Keyword::FOREIGN => {
81028102
self.expect_keyword_is(Keyword::KEY)?;
8103+
let index_name = self.parse_optional_ident()?;
81038104
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
81048105
self.expect_keyword_is(Keyword::REFERENCES)?;
81058106
let foreign_table = self.parse_object_name(false)?;
@@ -8122,6 +8123,7 @@ impl<'a> Parser<'a> {
81228123

81238124
Ok(Some(TableConstraint::ForeignKey {
81248125
name,
8126+
index_name,
81258127
columns,
81268128
foreign_table,
81278129
referred_columns,
@@ -8145,7 +8147,7 @@ impl<'a> Parser<'a> {
81458147

81468148
let name = match self.peek_token().token {
81478149
Token::Word(word) if word.keyword == Keyword::USING => None,
8148-
_ => self.parse_optional_indent()?,
8150+
_ => self.parse_optional_ident()?,
81498151
};
81508152

81518153
let index_type = self.parse_optional_using_then_index_type()?;
@@ -8176,7 +8178,7 @@ impl<'a> Parser<'a> {
81768178

81778179
let index_type_display = self.parse_index_type_display();
81788180

8179-
let opt_index_name = self.parse_optional_indent()?;
8181+
let opt_index_name = self.parse_optional_ident()?;
81808182

81818183
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
81828184

@@ -8286,7 +8288,7 @@ impl<'a> Parser<'a> {
82868288

82878289
/// Parse `[ident]`, mostly `ident` is name, like:
82888290
/// `window_name`, `index_name`, ...
8289-
pub fn parse_optional_indent(&mut self) -> Result<Option<Ident>, ParserError> {
8291+
pub fn parse_optional_ident(&mut self) -> Result<Option<Ident>, ParserError> {
82908292
self.maybe_parse(|parser| parser.parse_identifier())
82918293
}
82928294

@@ -15698,7 +15700,7 @@ impl<'a> Parser<'a> {
1569815700
pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
1569915701
let window_name = match self.peek_token().token {
1570015702
Token::Word(word) if word.keyword == Keyword::NoKeyword => {
15701-
self.parse_optional_indent()?
15703+
self.parse_optional_ident()?
1570215704
}
1570315705
_ => None,
1570415706
};

tests/sqlparser_common.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3791,6 +3791,7 @@ fn parse_create_table() {
37913791
vec![
37923792
TableConstraint::ForeignKey {
37933793
name: Some("fkey".into()),
3794+
index_name: None,
37943795
columns: vec!["lat".into()],
37953796
foreign_table: ObjectName::from(vec!["othertable3".into()]),
37963797
referred_columns: vec!["lat".into()],
@@ -3800,6 +3801,7 @@ fn parse_create_table() {
38003801
},
38013802
TableConstraint::ForeignKey {
38023803
name: Some("fkey2".into()),
3804+
index_name: None,
38033805
columns: vec!["lat".into()],
38043806
foreign_table: ObjectName::from(vec!["othertable4".into()]),
38053807
referred_columns: vec!["lat".into()],
@@ -3809,6 +3811,7 @@ fn parse_create_table() {
38093811
},
38103812
TableConstraint::ForeignKey {
38113813
name: None,
3814+
index_name: None,
38123815
columns: vec!["lat".into()],
38133816
foreign_table: ObjectName::from(vec!["othertable4".into()]),
38143817
referred_columns: vec!["lat".into()],
@@ -3818,6 +3821,7 @@ fn parse_create_table() {
38183821
},
38193822
TableConstraint::ForeignKey {
38203823
name: None,
3824+
index_name: None,
38213825
columns: vec!["lng".into()],
38223826
foreign_table: ObjectName::from(vec!["othertable4".into()]),
38233827
referred_columns: vec!["longitude".into()],
@@ -3914,6 +3918,7 @@ fn parse_create_table_with_constraint_characteristics() {
39143918
vec![
39153919
TableConstraint::ForeignKey {
39163920
name: Some("fkey".into()),
3921+
index_name: None,
39173922
columns: vec!["lat".into()],
39183923
foreign_table: ObjectName::from(vec!["othertable3".into()]),
39193924
referred_columns: vec!["lat".into()],
@@ -3927,6 +3932,7 @@ fn parse_create_table_with_constraint_characteristics() {
39273932
},
39283933
TableConstraint::ForeignKey {
39293934
name: Some("fkey2".into()),
3935+
index_name: None,
39303936
columns: vec!["lat".into()],
39313937
foreign_table: ObjectName::from(vec!["othertable4".into()]),
39323938
referred_columns: vec!["lat".into()],
@@ -3940,6 +3946,7 @@ fn parse_create_table_with_constraint_characteristics() {
39403946
},
39413947
TableConstraint::ForeignKey {
39423948
name: None,
3949+
index_name: None,
39433950
columns: vec!["lat".into()],
39443951
foreign_table: ObjectName::from(vec!["othertable4".into()]),
39453952
referred_columns: vec!["lat".into()],
@@ -3953,6 +3960,7 @@ fn parse_create_table_with_constraint_characteristics() {
39533960
},
39543961
TableConstraint::ForeignKey {
39553962
name: None,
3963+
index_name: None,
39563964
columns: vec!["lng".into()],
39573965
foreign_table: ObjectName::from(vec!["othertable4".into()]),
39583966
referred_columns: vec!["longitude".into()],

tests/sqlparser_mysql.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3988,6 +3988,13 @@ fn parse_straight_join() {
39883988
.verified_stmt("SELECT a.*, b.* FROM table_a STRAIGHT_JOIN table_b AS b ON a.b_id = b.id");
39893989
}
39903990

3991+
#[test]
3992+
fn mysql_foreign_key_with_index_name() {
3993+
mysql().verified_stmt(
3994+
"CREATE TABLE orders (customer_id INT, INDEX idx_customer (customer_id), CONSTRAINT fk_customer FOREIGN KEY idx_customer (customer_id) REFERENCES customers(id))",
3995+
);
3996+
}
3997+
39913998
#[test]
39923999
fn parse_drop_index() {
39934000
let sql = "DROP INDEX idx_name ON table_name";

0 commit comments

Comments
 (0)