From 9f0623133f1f086e21fed7c5289eb4687a549934 Mon Sep 17 00:00:00 2001 From: yukunpeng Date: Thu, 31 Aug 2023 19:37:19 +0800 Subject: [PATCH 1/3] feat:Add support for parsing the syntax of MySQL UNIQUE KEY. --- src/parser/mod.rs | 10 +++++-- tests/sqlparser_mysql.rs | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 846215249..1428325eb 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3894,9 +3894,15 @@ impl<'a> Parser<'a> { match next_token.token { Token::Word(w) if w.keyword == Keyword::PRIMARY || w.keyword == Keyword::UNIQUE => { let is_primary = w.keyword == Keyword::PRIMARY; - if is_primary { + let name = if is_primary { self.expect_keyword(Keyword::KEY)?; - } + name + } else if self.parse_keyword(Keyword::KEY) { + self.maybe_parse(|parser| parser.parse_identifier()) + } else { + name + }; + let columns = self.parse_parenthesized_column_list(Mandatory, false)?; Ok(Some(TableConstraint::Unique { name, diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index ab7997cdf..1ee38c11e 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -296,6 +296,62 @@ fn parse_create_table_auto_increment() { } } +#[test] +fn parse_create_table_unique_key() { + let sql = "CREATE TABLE foo (id INT PRIMARY KEY AUTO_INCREMENT, bar INT NOT NULL, UNIQUE KEY bar_key (bar))"; + let canonical = "CREATE TABLE foo (id INT PRIMARY KEY AUTO_INCREMENT, bar INT NOT NULL, CONSTRAINT bar_key UNIQUE (bar))"; + match mysql().one_statement_parses_to(sql, canonical) { + Statement::CreateTable { + name, + columns, + constraints, + .. + } => { + assert_eq!(name.to_string(), "foo"); + assert_eq!( + vec![TableConstraint::Unique { + name: Some(Ident::new("bar_key")), + columns: vec![Ident::new("bar")], + is_primary: false + }], + constraints + ); + assert_eq!( + vec![ + ColumnDef { + name: Ident::new("id"), + data_type: DataType::Int(None), + collation: None, + options: vec![ + ColumnOptionDef { + name: None, + option: ColumnOption::Unique { is_primary: true }, + }, + ColumnOptionDef { + name: None, + option: ColumnOption::DialectSpecific(vec![Token::make_keyword( + "AUTO_INCREMENT" + )]), + }, + ], + }, + ColumnDef { + name: Ident::new("bar"), + data_type: DataType::Int(None), + collation: None, + options: vec![ColumnOptionDef { + name: None, + option: ColumnOption::NotNull, + },], + }, + ], + columns + ); + } + _ => unreachable!(), + } +} + #[test] fn parse_create_table_comment() { let canonical = "CREATE TABLE foo (bar INT) COMMENT 'baz'"; From 02861953e65008147215139f1da08b2af7d235fc Mon Sep 17 00:00:00 2001 From: yukunpeng Date: Fri, 8 Sep 2023 12:50:58 +0800 Subject: [PATCH 2/3] optimize code logic --- src/parser/mod.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1428325eb..13fca65c0 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3894,14 +3894,17 @@ impl<'a> Parser<'a> { match next_token.token { Token::Word(w) if w.keyword == Keyword::PRIMARY || w.keyword == Keyword::UNIQUE => { let is_primary = w.keyword == Keyword::PRIMARY; - let name = if is_primary { + if is_primary { self.expect_keyword(Keyword::KEY)?; - name - } else if self.parse_keyword(Keyword::KEY) { - self.maybe_parse(|parser| parser.parse_identifier()) - } else { - name - }; + } + + let name = self + .maybe_parse(|parser| { + let _ = parser.parse_keyword(Keyword::KEY); + + parser.parse_identifier() + }) + .or(name); let columns = self.parse_parenthesized_column_list(Mandatory, false)?; Ok(Some(TableConstraint::Unique { From 137584cc7aafb35cd02125b0b484f2a6e968a685 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Fri, 8 Sep 2023 06:41:08 -0400 Subject: [PATCH 3/3] simplfy logic --- src/parser/mod.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 25b20512d..60f534f4a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3941,16 +3941,13 @@ impl<'a> Parser<'a> { match next_token.token { Token::Word(w) if w.keyword == Keyword::PRIMARY || w.keyword == Keyword::UNIQUE => { let is_primary = w.keyword == Keyword::PRIMARY; - if is_primary { - self.expect_keyword(Keyword::KEY)?; - } - let name = self - .maybe_parse(|parser| { - let _ = parser.parse_keyword(Keyword::KEY); + // parse optional [KEY] + let _ = self.parse_keyword(Keyword::KEY); - parser.parse_identifier() - }) + // optional constraint name + let name = self + .maybe_parse(|parser| parser.parse_identifier()) .or(name); let columns = self.parse_parenthesized_column_list(Mandatory, false)?;