This is an automated email from the ASF dual-hosted git repository.

iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new de2cc7b5 MySQL: Support `index_name` in FK constraints (#1871)
de2cc7b5 is described below

commit de2cc7b50233a5e5c0a5c9fe7ab08d23b18b9d5c
Author: Mohamed Abdeen <83442793+mohamedabdee...@users.noreply.github.com>
AuthorDate: Fri Jun 6 08:03:59 2025 +0100

    MySQL: Support `index_name` in FK constraints (#1871)
---
 src/ast/ddl.rs            |  7 ++++++-
 src/ast/spans.rs          |  2 ++
 src/parser/mod.rs         | 14 ++++++++------
 tests/sqlparser_common.rs |  8 ++++++++
 tests/sqlparser_mysql.rs  |  7 +++++++
 5 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index 06b85b0f..bbc15704 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -1019,6 +1019,9 @@ pub enum TableConstraint {
     /// }`).
     ForeignKey {
         name: Option<Ident>,
+        /// MySQL-specific field
+        /// 
<https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html>
+        index_name: Option<Ident>,
         columns: Vec<Ident>,
         foreign_table: ObjectName,
         referred_columns: Vec<Ident>,
@@ -1129,6 +1132,7 @@ impl fmt::Display for TableConstraint {
             }
             TableConstraint::ForeignKey {
                 name,
+                index_name,
                 columns,
                 foreign_table,
                 referred_columns,
@@ -1138,8 +1142,9 @@ impl fmt::Display for TableConstraint {
             } => {
                 write!(
                     f,
-                    "{}FOREIGN KEY ({}) REFERENCES {}",
+                    "{}FOREIGN KEY{} ({}) REFERENCES {}",
                     display_constraint_name(name),
+                    display_option_spaced(index_name),
                     display_comma_separated(columns),
                     foreign_table,
                 )?;
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index dd918c34..a1bad2c5 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -671,6 +671,7 @@ impl Spanned for TableConstraint {
             TableConstraint::ForeignKey {
                 name,
                 columns,
+                index_name,
                 foreign_table,
                 referred_columns,
                 on_delete,
@@ -679,6 +680,7 @@ impl Spanned for TableConstraint {
             } => union_spans(
                 name.iter()
                     .map(|i| i.span)
+                    .chain(index_name.iter().map(|i| i.span))
                     .chain(columns.iter().map(|i| i.span))
                     .chain(core::iter::once(foreign_table.span()))
                     .chain(referred_columns.iter().map(|i| i.span))
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 3e721072..677566c5 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -8061,7 +8061,7 @@ impl<'a> Parser<'a> {
                 let nulls_distinct = self.parse_optional_nulls_distinct()?;
 
                 // optional index name
-                let index_name = self.parse_optional_indent()?;
+                let index_name = self.parse_optional_ident()?;
                 let index_type = self.parse_optional_using_then_index_type()?;
 
                 let columns = self.parse_parenthesized_column_list(Mandatory, 
false)?;
@@ -8083,7 +8083,7 @@ impl<'a> Parser<'a> {
                 self.expect_keyword_is(Keyword::KEY)?;
 
                 // optional index name
-                let index_name = self.parse_optional_indent()?;
+                let index_name = self.parse_optional_ident()?;
                 let index_type = self.parse_optional_using_then_index_type()?;
 
                 let columns = self.parse_parenthesized_column_list(Mandatory, 
false)?;
@@ -8100,6 +8100,7 @@ impl<'a> Parser<'a> {
             }
             Token::Word(w) if w.keyword == Keyword::FOREIGN => {
                 self.expect_keyword_is(Keyword::KEY)?;
+                let index_name = self.parse_optional_ident()?;
                 let columns = self.parse_parenthesized_column_list(Mandatory, 
false)?;
                 self.expect_keyword_is(Keyword::REFERENCES)?;
                 let foreign_table = self.parse_object_name(false)?;
@@ -8122,6 +8123,7 @@ impl<'a> Parser<'a> {
 
                 Ok(Some(TableConstraint::ForeignKey {
                     name,
+                    index_name,
                     columns,
                     foreign_table,
                     referred_columns,
@@ -8145,7 +8147,7 @@ impl<'a> Parser<'a> {
 
                 let name = match self.peek_token().token {
                     Token::Word(word) if word.keyword == Keyword::USING => 
None,
-                    _ => self.parse_optional_indent()?,
+                    _ => self.parse_optional_ident()?,
                 };
 
                 let index_type = self.parse_optional_using_then_index_type()?;
@@ -8176,7 +8178,7 @@ impl<'a> Parser<'a> {
 
                 let index_type_display = self.parse_index_type_display();
 
-                let opt_index_name = self.parse_optional_indent()?;
+                let opt_index_name = self.parse_optional_ident()?;
 
                 let columns = self.parse_parenthesized_column_list(Mandatory, 
false)?;
 
@@ -8286,7 +8288,7 @@ impl<'a> Parser<'a> {
 
     /// Parse `[ident]`, mostly `ident` is name, like:
     /// `window_name`, `index_name`, ...
-    pub fn parse_optional_indent(&mut self) -> Result<Option<Ident>, 
ParserError> {
+    pub fn parse_optional_ident(&mut self) -> Result<Option<Ident>, 
ParserError> {
         self.maybe_parse(|parser| parser.parse_identifier())
     }
 
@@ -15698,7 +15700,7 @@ impl<'a> Parser<'a> {
     pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
         let window_name = match self.peek_token().token {
             Token::Word(word) if word.keyword == Keyword::NoKeyword => {
-                self.parse_optional_indent()?
+                self.parse_optional_ident()?
             }
             _ => None,
         };
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index a1a8fc3b..0431c720 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -3791,6 +3791,7 @@ fn parse_create_table() {
                 vec![
                     TableConstraint::ForeignKey {
                         name: Some("fkey".into()),
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable3".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3800,6 +3801,7 @@ fn parse_create_table() {
                     },
                     TableConstraint::ForeignKey {
                         name: Some("fkey2".into()),
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3809,6 +3811,7 @@ fn parse_create_table() {
                     },
                     TableConstraint::ForeignKey {
                         name: None,
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3818,6 +3821,7 @@ fn parse_create_table() {
                     },
                     TableConstraint::ForeignKey {
                         name: None,
+                        index_name: None,
                         columns: vec!["lng".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["longitude".into()],
@@ -3914,6 +3918,7 @@ fn parse_create_table_with_constraint_characteristics() {
                 vec![
                     TableConstraint::ForeignKey {
                         name: Some("fkey".into()),
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable3".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3927,6 +3932,7 @@ fn parse_create_table_with_constraint_characteristics() {
                     },
                     TableConstraint::ForeignKey {
                         name: Some("fkey2".into()),
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3940,6 +3946,7 @@ fn parse_create_table_with_constraint_characteristics() {
                     },
                     TableConstraint::ForeignKey {
                         name: None,
+                        index_name: None,
                         columns: vec!["lat".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["lat".into()],
@@ -3953,6 +3960,7 @@ fn parse_create_table_with_constraint_characteristics() {
                     },
                     TableConstraint::ForeignKey {
                         name: None,
+                        index_name: None,
                         columns: vec!["lng".into()],
                         foreign_table: 
ObjectName::from(vec!["othertable4".into()]),
                         referred_columns: vec!["longitude".into()],
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index 0800c329..b1b7d539 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -3988,6 +3988,13 @@ fn parse_straight_join() {
         .verified_stmt("SELECT a.*, b.* FROM table_a STRAIGHT_JOIN table_b AS 
b ON a.b_id = b.id");
 }
 
+#[test]
+fn mysql_foreign_key_with_index_name() {
+    mysql().verified_stmt(
+        "CREATE TABLE orders (customer_id INT, INDEX idx_customer 
(customer_id), CONSTRAINT fk_customer FOREIGN KEY idx_customer (customer_id) 
REFERENCES customers(id))",
+    );
+}
+
 #[test]
 fn parse_drop_index() {
     let sql = "DROP INDEX idx_name ON table_name";


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@datafusion.apache.org
For additional commands, e-mail: commits-h...@datafusion.apache.org

Reply via email to