From aec0d2ee4741f0b4d81a375a00af9d974bde40a0 Mon Sep 17 00:00:00 2001 From: vimko <1399950+vimko@users.noreply.github.com> Date: Wed, 28 May 2025 21:52:15 +0800 Subject: [PATCH 1/3] mysql support `DROP INDEX idx_a ON table_a` and `ALTER TABLE table_a DROP INDEX idx_a` --- src/ast/ddl.rs | 9 +++++++++ src/ast/mod.rs | 22 ++++++++++++++++++++++ src/ast/spans.rs | 2 ++ src/parser/mod.rs | 27 ++++++++++++++++++++++++++- tests/sqlparser_common.rs | 4 +++- tests/sqlparser_mysql.rs | 23 +++++++++++++++++++++++ 6 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index bbfa7d3c9..323009222 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -186,6 +186,14 @@ pub enum AlterTableOperation { DropForeignKey { name: Ident, }, + /// `DROP INDEX ` + /// + /// Note: this is a [MySQL]-specific operation. + /// + /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html + DropIndex { + name: Ident, + }, /// `ENABLE ALWAYS RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. @@ -605,6 +613,7 @@ impl fmt::Display for AlterTableOperation { } AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"), AlterTableOperation::DropForeignKey { name } => write!(f, "DROP FOREIGN KEY {name}"), + AlterTableOperation::DropIndex { name } => write!(f, "DROP INDEX {name}"), AlterTableOperation::DropColumn { column_name, if_exists, diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 8e7bec3f4..6c60dd55e 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3208,6 +3208,17 @@ pub enum Statement { /// `CREATE INDEX` /// ``` CreateIndex(CreateIndex), + /// DROP INDEX + /// + /// ```sql + /// DROP INDEX index_name ON tbl_name + /// ``` + /// See [MySql](https://dev.mysql.com/doc/refman/8.4/en/drop-index.html) + /// TODO: No support `[algorithm_option | lock_option]` + DropIndex { + index_name: ObjectName, + table_name: Option, + }, /// ```sql /// CREATE ROLE /// ``` @@ -4916,6 +4927,17 @@ impl fmt::Display for Statement { Ok(()) } Statement::CreateIndex(create_index) => create_index.fmt(f), + Statement::DropIndex { + index_name, + table_name, + } => { + write!(f, "DROP INDEX")?; + match &table_name { + Some(table_name) => write!(f, " {index_name} ON {table_name}")?, + None => write!(f, " {index_name}")?, + }; + Ok(()) + } Statement::CreateExtension { name, if_not_exists, diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 1c28b62cc..d9c90def6 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -421,6 +421,7 @@ impl Spanned for Statement { .chain(module_args.iter().map(|i| i.span)), ), Statement::CreateIndex(create_index) => create_index.span(), + Statement::DropIndex { .. } => Span::empty(), Statement::CreateRole { .. } => Span::empty(), Statement::CreateSecret { .. } => Span::empty(), Statement::CreateConnector { .. } => Span::empty(), @@ -1110,6 +1111,7 @@ impl Spanned for AlterTableOperation { .union_opt(&with_name.as_ref().map(|n| n.span)), AlterTableOperation::DropPrimaryKey => Span::empty(), AlterTableOperation::DropForeignKey { name } => name.span, + AlterTableOperation::DropIndex { name } => name.span, AlterTableOperation::EnableAlwaysRule { name } => name.span, AlterTableOperation::EnableAlwaysTrigger { name } => name.span, AlterTableOperation::EnableReplicaRule { name } => name.span, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 4299d1566..710388f2a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5347,6 +5347,24 @@ impl<'a> Parser<'a> { }) } + /// Parse statements of the DropIndex type such as: + /// + /// ```sql + /// DROP Index idx_name ON table_name + /// ``` + pub fn parse_drop_index(&mut self) -> Result { + let index_name = self.parse_object_name(false)?; + let table_name = if self.parse_keyword(Keyword::ON) { + Some(self.parse_object_name(false)?) + } else { + None + }; + Ok(Statement::DropIndex { + index_name, + table_name, + }) + } + /// Parse statements of the DropTrigger type such as: /// /// ```sql @@ -6196,7 +6214,11 @@ impl<'a> Parser<'a> { } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) { ObjectType::MaterializedView } else if self.parse_keyword(Keyword::INDEX) { - ObjectType::Index + if dialect_of!(self is MySqlDialect){ + return self.parse_drop_index(); + }else { + ObjectType::Index + } } else if self.parse_keyword(Keyword::ROLE) { ObjectType::Role } else if self.parse_keyword(Keyword::SCHEMA) { @@ -8599,6 +8621,9 @@ impl<'a> Parser<'a> { } else if self.parse_keywords(&[Keyword::FOREIGN, Keyword::KEY]) { let name = self.parse_identifier()?; AlterTableOperation::DropForeignKey { name } + } else if self.parse_keyword(Keyword::INDEX) { + let name = self.parse_identifier()?; + AlterTableOperation::DropIndex { name } } else if self.parse_keyword(Keyword::PROJECTION) && dialect_of!(self is ClickHouseDialect|GenericDialect) { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 86c473d7d..dba10be86 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -9099,7 +9099,9 @@ fn test_create_index_with_with_clause() { #[test] fn parse_drop_index() { let sql = "DROP INDEX idx_a"; - match verified_stmt(sql) { + // MySql dialect doesn't support `DROP INDEX idx_a`,you need to specify a specific table, please refer: + // [MySql](https://dev.mysql.com/doc/refman/8.4/en/drop-index.html) + match all_dialects_except(|d| d.is::()).verified_stmt(sql) { Statement::Drop { names, object_type, .. } => { diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index bcde14ee5..c4bcbe069 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -3985,3 +3985,26 @@ fn parse_straight_join() { mysql() .verified_stmt("SELECT a.*, b.* FROM table_a STRAIGHT_JOIN table_b AS b ON a.b_id = b.id"); } + +#[test] +fn parse_drop_index() { + let sql_drop_index = "DROP INDEX idx_name ON tab_name;"; + let drop_stmt = mysql().one_statement_parses_to(sql_drop_index, ""); + assert_eq!( + drop_stmt, + Statement::DropIndex { + index_name: ObjectName::from(vec![Ident::new("idx_name")]), + table_name: Some(ObjectName::from(vec![Ident::new("tab_name")])), + } + ); +} + +#[test] +fn parse_alter_table_drop_index() { + assert_matches!( + alter_table_op( + mysql_and_generic().verified_stmt("ALTER TABLE tab DROP INDEX idx_index") + ), + AlterTableOperation::DropIndex { name } if name.value == "idx_index" + ); +} \ No newline at end of file From 0a2082feb9ec31991775f6c5431f11311c70c61a Mon Sep 17 00:00:00 2001 From: vimko <1399950+vimko@users.noreply.github.com> Date: Wed, 4 Jun 2025 22:51:26 +0800 Subject: [PATCH 2/3] mysql support ALTER TABLE table_a DROP INDEX idx_a --- src/ast/mod.rs | 22 ---------------------- src/ast/spans.rs | 1 - src/parser/mod.rs | 24 +----------------------- 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 98b86428e..653f58e4d 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3208,17 +3208,6 @@ pub enum Statement { /// `CREATE INDEX` /// ``` CreateIndex(CreateIndex), - /// DROP INDEX - /// - /// ```sql - /// DROP INDEX index_name ON tbl_name - /// ``` - /// See [MySql](https://dev.mysql.com/doc/refman/8.4/en/drop-index.html) - /// TODO: No support `[algorithm_option | lock_option]` - DropIndex { - index_name: ObjectName, - table_name: Option, - }, /// ```sql /// CREATE ROLE /// ``` @@ -4930,17 +4919,6 @@ impl fmt::Display for Statement { Ok(()) } Statement::CreateIndex(create_index) => create_index.fmt(f), - Statement::DropIndex { - index_name, - table_name, - } => { - write!(f, "DROP INDEX")?; - match &table_name { - Some(table_name) => write!(f, " {index_name} ON {table_name}")?, - None => write!(f, " {index_name}")?, - }; - Ok(()) - } Statement::CreateExtension { name, if_not_exists, diff --git a/src/ast/spans.rs b/src/ast/spans.rs index b7f860bec..93af8208b 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -421,7 +421,6 @@ impl Spanned for Statement { .chain(module_args.iter().map(|i| i.span)), ), Statement::CreateIndex(create_index) => create_index.span(), - Statement::DropIndex { .. } => Span::empty(), Statement::CreateRole { .. } => Span::empty(), Statement::CreateSecret { .. } => Span::empty(), Statement::CreateConnector { .. } => Span::empty(), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 09c3ca1e4..1b46aa213 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5353,24 +5353,6 @@ impl<'a> Parser<'a> { }) } - /// Parse statements of the DropIndex type such as: - /// - /// ```sql - /// DROP Index idx_name ON table_name - /// ``` - pub fn parse_drop_index(&mut self) -> Result { - let index_name = self.parse_object_name(false)?; - let table_name = if self.parse_keyword(Keyword::ON) { - Some(self.parse_object_name(false)?) - } else { - None - }; - Ok(Statement::DropIndex { - index_name, - table_name, - }) - } - /// Parse statements of the DropTrigger type such as: /// /// ```sql @@ -6220,11 +6202,7 @@ impl<'a> Parser<'a> { } else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) { ObjectType::MaterializedView } else if self.parse_keyword(Keyword::INDEX) { - if dialect_of!(self is MySqlDialect){ - return self.parse_drop_index(); - }else { - ObjectType::Index - } + ObjectType::Index } else if self.parse_keyword(Keyword::ROLE) { ObjectType::Role } else if self.parse_keyword(Keyword::SCHEMA) { From 3676f6ef1a0c170a662cf00dc6d05e9f6c4464e5 Mon Sep 17 00:00:00 2001 From: vimko <1399950+vimko@users.noreply.github.com> Date: Sun, 8 Jun 2025 15:31:57 +0800 Subject: [PATCH 3/3] fixing broken unit tests --- src/ast/ddl.rs | 2 -- tests/sqlparser_common.rs | 4 +--- tests/sqlparser_mysql.rs | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 677c8a6ee..cf44ad6fa 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -189,8 +189,6 @@ pub enum AlterTableOperation { }, /// `DROP INDEX ` /// - /// Note: this is a [MySQL]-specific operation. - /// /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html DropIndex { name: Ident, diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index a0f81aaa8..a1a8fc3b3 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -9132,9 +9132,7 @@ fn test_create_index_with_with_clause() { #[test] fn parse_drop_index() { let sql = "DROP INDEX idx_a"; - // MySql dialect doesn't support `DROP INDEX idx_a`,you need to specify a specific table, please refer: - // [MySql](https://dev.mysql.com/doc/refman/8.4/en/drop-index.html) - match all_dialects_except(|d| d.is::()).verified_stmt(sql) { + match verified_stmt(sql) { Statement::Drop { names, object_type, .. } => { diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 60810b3d6..60bee6d21 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -4027,4 +4027,4 @@ fn parse_alter_table_drop_index() { ), AlterTableOperation::DropIndex { name } if name.value == "idx_index" ); -} \ No newline at end of file +}