From 6dd01308add0cf43d73cd2268b82bbfe5f0accaa Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Tue, 24 Dec 2024 23:15:14 +0800 Subject: [PATCH 1/8] Add support for MYSQL's `RENAME TABLE` expr --- src/ast/mod.rs | 26 ++++++++++ src/ast/spans.rs | 1 + src/dialect/mod.rs | 5 ++ src/dialect/mysql.rs | 5 ++ src/parser/mod.rs | 20 +++++++- tests/sqlparser_common.rs | 105 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 1 deletion(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9fb2bb9c9..6b19d7e0b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3401,6 +3401,13 @@ pub enum Statement { partitioned: Option>, table_format: Option, }, + /// ```sql + /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ... + /// ``` + /// renames one or more tables + /// + /// See Mysql + RenameTable { operations: Vec }, } impl fmt::Display for Statement { @@ -4940,6 +4947,9 @@ impl fmt::Display for Statement { } Ok(()) } + Statement::RenameTable { operations } => { + write!(f, "RENAME TABLE {}", display_comma_separated(operations)) + } } } } @@ -7642,6 +7652,22 @@ impl Display for JsonNullClause { } } +/// rename object definition +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct RenameObjectDef { + pub old_name: ObjectName, + pub new_name: ObjectName, +} + +impl fmt::Display for RenameObjectDef { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} TO {}", self.old_name, self.new_name)?; + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 9ba3bdd9b..30a1b7588 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -491,6 +491,7 @@ impl Spanned for Statement { Statement::NOTIFY { .. } => Span::empty(), Statement::LoadData { .. } => Span::empty(), Statement::UNLISTEN { .. } => Span::empty(), + Statement::RenameTable { .. } => Span::empty(), } } } diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 7a71d662f..6c753695d 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -715,6 +715,11 @@ pub trait Dialect: Debug + Any { true } + // Returns true if the dialect supports the `RENAME TABLE` statement + fn supports_rename_table(&self) -> bool { + false + } + /// Returns true if this dialect supports the `LIKE 'pattern'` option in /// a `SHOW` statement before the `IN` option fn supports_show_like_before_in(&self) -> bool { diff --git a/src/dialect/mysql.rs b/src/dialect/mysql.rs index 197ce48d4..d10b798d7 100644 --- a/src/dialect/mysql.rs +++ b/src/dialect/mysql.rs @@ -102,6 +102,11 @@ impl Dialect for MySqlDialect { fn supports_create_table_select(&self) -> bool { true } + + /// see + fn supports_rename_table(&self) -> bool { + true + } } /// `LOCK TABLES` diff --git a/src/parser/mod.rs b/src/parser/mod.rs index cc0a57e4d..8f8968e65 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -33,8 +33,8 @@ use IsLateral::*; use IsOptional::*; use crate::ast::helpers::stmt_create_table::{CreateTableBuilder, CreateTableConfiguration}; -use crate::ast::Statement::CreatePolicy; use crate::ast::*; +use crate::ast::{RenameObjectDef, Statement::CreatePolicy}; use crate::dialect::*; use crate::keywords::{Keyword, ALL_KEYWORDS}; use crate::tokenizer::*; @@ -547,6 +547,10 @@ impl<'a> Parser<'a> { // `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html Keyword::PRAGMA => self.parse_pragma(), Keyword::UNLOAD => self.parse_unload(), + // `RENAME TABLE` is mysql specific https://dev.mysql.com/doc/refman/9.1/en/rename-table.html + Keyword::RENAME if self.dialect.supports_rename_table() => { + self.parse_rename_table() + } // `INSTALL` is duckdb specific https://duckdb.org/docs/extensions/overview Keyword::INSTALL if dialect_of!(self is DuckDbDialect | GenericDialect) => { self.parse_install() @@ -1044,6 +1048,12 @@ impl<'a> Parser<'a> { Ok(Statement::NOTIFY { channel, payload }) } + pub fn parse_rename_table(&mut self) -> Result { + self.expect_keyword(Keyword::TABLE)?; + let operations = self.parse_comma_separated(Parser::parse_rename_object_def)?; + Ok(Statement::RenameTable { operations }) + } + // Tries to parse an expression by matching the specified word to known keywords that have a special meaning in the dialect. // Returns `None if no match is found. fn parse_expr_prefix_by_reserved_word( @@ -6682,6 +6692,14 @@ impl<'a> Parser<'a> { Ok(Tag::new(name, value)) } + pub(crate) fn parse_rename_object_def(&mut self) -> Result { + let old_name = self.parse_object_name(false)?; + self.expect_keyword(Keyword::TO)?; + let new_name = self.parse_object_name(false)?; + + Ok(RenameObjectDef { old_name, new_name }) + } + fn parse_optional_column_option_generated( &mut self, ) -> Result, ParserError> { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 79f5c8d32..9b1f838b0 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4026,6 +4026,111 @@ fn parse_alter_table() { } } +#[test] +fn parse_rename_table() { + let dialects = all_dialects_where(|d| d.supports_rename_table()); + + match dialects.verified_stmt("RENAME TABLE `test`.`test1` TO `test_db`.`test2`") { + Statement::RenameTable { operations } => { + assert_eq!( + vec![RenameObjectDef { + old_name: ObjectName(vec![ + Ident { + value: "test".to_string(), + quote_style: Some('`'), + span: Span::empty(), + }, + Ident { + value: "test1".to_string(), + quote_style: Some('`'), + span: Span::empty(), + } + ]), + new_name: ObjectName(vec![ + Ident { + value: "test_db".to_string(), + quote_style: Some('`'), + span: Span::empty(), + }, + Ident { + value: "test2".to_string(), + quote_style: Some('`'), + span: Span::empty(), + } + ]), + }], + operations + ); + } + _ => unreachable!(), + }; + + match dialects.verified_stmt( + "RENAME TABLE old_table1 TO new_table1, old_table2 TO new_table2, old_table3 TO new_table3", + ) { + Statement::RenameTable { operations } => { + assert_eq!( + vec![ + RenameObjectDef { + old_name: ObjectName(vec![Ident { + value: "old_table1".to_string(), + quote_style: None, + span: Span::empty(), + }]), + new_name: ObjectName(vec![Ident { + value: "new_table1".to_string(), + quote_style: None, + span: Span::empty(), + }]), + }, + RenameObjectDef { + old_name: ObjectName(vec![Ident { + value: "old_table2".to_string(), + quote_style: None, + span: Span::empty(), + }]), + new_name: ObjectName(vec![Ident { + value: "new_table2".to_string(), + quote_style: None, + span: Span::empty(), + }]), + }, + RenameObjectDef { + old_name: ObjectName(vec![Ident { + value: "old_table3".to_string(), + quote_style: None, + span: Span::empty(), + }]), + new_name: ObjectName(vec![Ident { + value: "new_table3".to_string(), + quote_style: None, + span: Span::empty(), + }]), + } + ], + operations + ); + } + _ => unreachable!(), + }; + + assert_eq!( + dialects + .parse_sql_statements("RENAME TABLE `old_table` TO new_table a") + .unwrap_err(), + ParserError::ParserError("Expected: end of statement, found: a".to_string()) + ); + + let dialects = all_dialects_where(|d| !d.supports_rename_table()); + + assert_eq!( + dialects + .parse_sql_statements("RENAME TABLE `old_table` TO new_table") + .unwrap_err(), + ParserError::ParserError("Expected: an SQL statement, found: RENAME".to_string()) + ); +} + #[test] fn test_alter_table_with_on_cluster() { match all_dialects() From 74643f9959b6b9e1ca815102b0c5038a5d573b47 Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Wed, 25 Dec 2024 00:14:05 +0800 Subject: [PATCH 2/8] more rusty --- src/parser/mod.rs | 16 +++++++++------- tests/sqlparser_common.rs | 11 ++++++++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8f8968e65..ad758894d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -548,9 +548,7 @@ impl<'a> Parser<'a> { Keyword::PRAGMA => self.parse_pragma(), Keyword::UNLOAD => self.parse_unload(), // `RENAME TABLE` is mysql specific https://dev.mysql.com/doc/refman/9.1/en/rename-table.html - Keyword::RENAME if self.dialect.supports_rename_table() => { - self.parse_rename_table() - } + Keyword::RENAME => self.parse_rename(), // `INSTALL` is duckdb specific https://duckdb.org/docs/extensions/overview Keyword::INSTALL if dialect_of!(self is DuckDbDialect | GenericDialect) => { self.parse_install() @@ -1048,10 +1046,14 @@ impl<'a> Parser<'a> { Ok(Statement::NOTIFY { channel, payload }) } - pub fn parse_rename_table(&mut self) -> Result { - self.expect_keyword(Keyword::TABLE)?; - let operations = self.parse_comma_separated(Parser::parse_rename_object_def)?; - Ok(Statement::RenameTable { operations }) + pub fn parse_rename(&mut self) -> Result { + if self.dialect.supports_rename_table() && self.peek_keyword(Keyword::TABLE) { + self.expect_keyword(Keyword::TABLE)?; + let operations = self.parse_comma_separated(Parser::parse_rename_object_def)?; + Ok(Statement::RenameTable { operations }) + } else { + self.expected("an object type after RENAME", self.peek_token()) + } } // Tries to parse an expression by matching the specified word to known keywords that have a special meaning in the dialect. diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 9b1f838b0..a8240e219 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4121,13 +4121,22 @@ fn parse_rename_table() { ParserError::ParserError("Expected: end of statement, found: a".to_string()) ); + assert_eq!( + dialects + .parse_sql_statements("RENAME TABLE1 `old_table` TO new_table a") + .unwrap_err(), + ParserError::ParserError( + "Expected: an object type after RENAME, found: TABLE1".to_string() + ) + ); + let dialects = all_dialects_where(|d| !d.supports_rename_table()); assert_eq!( dialects .parse_sql_statements("RENAME TABLE `old_table` TO new_table") .unwrap_err(), - ParserError::ParserError("Expected: an SQL statement, found: RENAME".to_string()) + ParserError::ParserError("Expected: an object type after RENAME, found: TABLE".to_string()) ); } From 51c77f2adb8774704c70af4e3293021a053f2793 Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Fri, 27 Dec 2024 22:02:26 +0800 Subject: [PATCH 3/8] Update src/parser/mod.rs add more document Co-authored-by: Ifeanyi Ubah --- src/parser/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index ad758894d..53c4ad9b8 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1046,6 +1046,7 @@ impl<'a> Parser<'a> { Ok(Statement::NOTIFY { channel, payload }) } + /// Parses a `RENAME TABLE` statement. See [Statement::Rename] pub fn parse_rename(&mut self) -> Result { if self.dialect.supports_rename_table() && self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?; From 6ff9371557815573b2a6fddf1a6535c92f74ae51 Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Fri, 27 Dec 2024 22:55:45 +0800 Subject: [PATCH 4/8] more rusty --- src/ast/mod.rs | 12 ++++--- src/parser/mod.rs | 22 ++++++------ tests/sqlparser_common.rs | 74 ++++++++++----------------------------- 3 files changed, 36 insertions(+), 72 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6b19d7e0b..c460fd0e1 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3404,10 +3404,10 @@ pub enum Statement { /// ```sql /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ... /// ``` - /// renames one or more tables + /// Renames one or more tables /// /// See Mysql - RenameTable { operations: Vec }, + RenameTable(Vec), } impl fmt::Display for Statement { @@ -4947,8 +4947,12 @@ impl fmt::Display for Statement { } Ok(()) } - Statement::RenameTable { operations } => { - write!(f, "RENAME TABLE {}", display_comma_separated(operations)) + Statement::RenameTable(rename_object_defs) => { + write!( + f, + "RENAME TABLE {}", + display_comma_separated(rename_object_defs) + ) } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 53c4ad9b8..fcea01542 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -33,8 +33,8 @@ use IsLateral::*; use IsOptional::*; use crate::ast::helpers::stmt_create_table::{CreateTableBuilder, CreateTableConfiguration}; +use crate::ast::Statement::CreatePolicy; use crate::ast::*; -use crate::ast::{RenameObjectDef, Statement::CreatePolicy}; use crate::dialect::*; use crate::keywords::{Keyword, ALL_KEYWORDS}; use crate::tokenizer::*; @@ -1050,10 +1050,16 @@ impl<'a> Parser<'a> { pub fn parse_rename(&mut self) -> Result { if self.dialect.supports_rename_table() && self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?; - let operations = self.parse_comma_separated(Parser::parse_rename_object_def)?; - Ok(Statement::RenameTable { operations }) + let rename_object_defs = self.parse_comma_separated(|parser| { + let old_name = parser.parse_object_name(false)?; + parser.expect_keyword(Keyword::TO)?; + let new_name = parser.parse_object_name(false)?; + + Ok(RenameObjectDef { old_name, new_name }) + })?; + Ok(Statement::RenameTable(rename_object_defs)) } else { - self.expected("an object type after RENAME", self.peek_token()) + self.expected("KEYWORD `TABLE` after RENAME", self.peek_token()) } } @@ -6695,14 +6701,6 @@ impl<'a> Parser<'a> { Ok(Tag::new(name, value)) } - pub(crate) fn parse_rename_object_def(&mut self) -> Result { - let old_name = self.parse_object_name(false)?; - self.expect_keyword(Keyword::TO)?; - let new_name = self.parse_object_name(false)?; - - Ok(RenameObjectDef { old_name, new_name }) - } - fn parse_optional_column_option_generated( &mut self, ) -> Result, ParserError> { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index a8240e219..12dd66105 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4031,35 +4031,19 @@ fn parse_rename_table() { let dialects = all_dialects_where(|d| d.supports_rename_table()); match dialects.verified_stmt("RENAME TABLE `test`.`test1` TO `test_db`.`test2`") { - Statement::RenameTable { operations } => { + Statement::RenameTable(rename_object_defs) => { assert_eq!( vec![RenameObjectDef { old_name: ObjectName(vec![ - Ident { - value: "test".to_string(), - quote_style: Some('`'), - span: Span::empty(), - }, - Ident { - value: "test1".to_string(), - quote_style: Some('`'), - span: Span::empty(), - } + Ident::with_quote('`', "test".to_string()), + Ident::with_quote('`', "test1".to_string()), ]), new_name: ObjectName(vec![ - Ident { - value: "test_db".to_string(), - quote_style: Some('`'), - span: Span::empty(), - }, - Ident { - value: "test2".to_string(), - quote_style: Some('`'), - span: Span::empty(), - } + Ident::with_quote('`', "test_db".to_string()), + Ident::with_quote('`', "test2".to_string()), ]), }], - operations + rename_object_defs ); } _ => unreachable!(), @@ -4068,47 +4052,23 @@ fn parse_rename_table() { match dialects.verified_stmt( "RENAME TABLE old_table1 TO new_table1, old_table2 TO new_table2, old_table3 TO new_table3", ) { - Statement::RenameTable { operations } => { + Statement::RenameTable(rename_object_defs) => { assert_eq!( vec![ RenameObjectDef { - old_name: ObjectName(vec![Ident { - value: "old_table1".to_string(), - quote_style: None, - span: Span::empty(), - }]), - new_name: ObjectName(vec![Ident { - value: "new_table1".to_string(), - quote_style: None, - span: Span::empty(), - }]), + old_name: ObjectName(vec![Ident::new("old_table1".to_string())]), + new_name: ObjectName(vec![Ident::new("new_table1".to_string())]), }, RenameObjectDef { - old_name: ObjectName(vec![Ident { - value: "old_table2".to_string(), - quote_style: None, - span: Span::empty(), - }]), - new_name: ObjectName(vec![Ident { - value: "new_table2".to_string(), - quote_style: None, - span: Span::empty(), - }]), + old_name: ObjectName(vec![Ident::new("old_table2".to_string())]), + new_name: ObjectName(vec![Ident::new("new_table2".to_string())]), }, RenameObjectDef { - old_name: ObjectName(vec![Ident { - value: "old_table3".to_string(), - quote_style: None, - span: Span::empty(), - }]), - new_name: ObjectName(vec![Ident { - value: "new_table3".to_string(), - quote_style: None, - span: Span::empty(), - }]), + old_name: ObjectName(vec![Ident::new("old_table3".to_string())]), + new_name: ObjectName(vec![Ident::new("new_table3".to_string())]), } ], - operations + rename_object_defs ); } _ => unreachable!(), @@ -4126,7 +4086,7 @@ fn parse_rename_table() { .parse_sql_statements("RENAME TABLE1 `old_table` TO new_table a") .unwrap_err(), ParserError::ParserError( - "Expected: an object type after RENAME, found: TABLE1".to_string() + "Expected: KEYWORD `TABLE` after RENAME, found: TABLE1".to_string() ) ); @@ -4136,7 +4096,9 @@ fn parse_rename_table() { dialects .parse_sql_statements("RENAME TABLE `old_table` TO new_table") .unwrap_err(), - ParserError::ParserError("Expected: an object type after RENAME, found: TABLE".to_string()) + ParserError::ParserError( + "Expected: KEYWORD `TABLE` after RENAME, found: TABLE".to_string() + ) ); } From 489da0334300502b453ac5a858f7db5445d3e3de Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Fri, 27 Dec 2024 23:24:14 +0800 Subject: [PATCH 5/8] fix doc error --- src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index fcea01542..8de71f656 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1046,7 +1046,7 @@ impl<'a> Parser<'a> { Ok(Statement::NOTIFY { channel, payload }) } - /// Parses a `RENAME TABLE` statement. See [Statement::Rename] + /// Parses a `RENAME TABLE` statement. See [Statement::RenameTable] pub fn parse_rename(&mut self) -> Result { if self.dialect.supports_rename_table() && self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?; From 9224db92080133e31912119addfca6f6f0a601ae Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Sun, 29 Dec 2024 21:25:59 +0800 Subject: [PATCH 6/8] remove redundant code --- src/ast/mod.rs | 6 +++--- src/dialect/mod.rs | 5 ----- src/dialect/mysql.rs | 5 ----- src/parser/mod.rs | 5 +++-- tests/sqlparser_common.rs | 41 ++++++++++++--------------------------- 5 files changed, 18 insertions(+), 44 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index c460fd0e1..137500bfe 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3407,7 +3407,7 @@ pub enum Statement { /// Renames one or more tables /// /// See Mysql - RenameTable(Vec), + RenameTable(Vec), } impl fmt::Display for Statement { @@ -7660,12 +7660,12 @@ impl Display for JsonNullClause { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] -pub struct RenameObjectDef { +pub struct RenameTable { pub old_name: ObjectName, pub new_name: ObjectName, } -impl fmt::Display for RenameObjectDef { +impl fmt::Display for RenameTable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} TO {}", self.old_name, self.new_name)?; Ok(()) diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 6c753695d..7a71d662f 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -715,11 +715,6 @@ pub trait Dialect: Debug + Any { true } - // Returns true if the dialect supports the `RENAME TABLE` statement - fn supports_rename_table(&self) -> bool { - false - } - /// Returns true if this dialect supports the `LIKE 'pattern'` option in /// a `SHOW` statement before the `IN` option fn supports_show_like_before_in(&self) -> bool { diff --git a/src/dialect/mysql.rs b/src/dialect/mysql.rs index d10b798d7..197ce48d4 100644 --- a/src/dialect/mysql.rs +++ b/src/dialect/mysql.rs @@ -102,11 +102,6 @@ impl Dialect for MySqlDialect { fn supports_create_table_select(&self) -> bool { true } - - /// see - fn supports_rename_table(&self) -> bool { - true - } } /// `LOCK TABLES` diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8de71f656..9a444f7fb 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1047,15 +1047,16 @@ impl<'a> Parser<'a> { } /// Parses a `RENAME TABLE` statement. See [Statement::RenameTable] + /// see pub fn parse_rename(&mut self) -> Result { - if self.dialect.supports_rename_table() && self.peek_keyword(Keyword::TABLE) { + if self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?; let rename_object_defs = self.parse_comma_separated(|parser| { let old_name = parser.parse_object_name(false)?; parser.expect_keyword(Keyword::TO)?; let new_name = parser.parse_object_name(false)?; - Ok(RenameObjectDef { old_name, new_name }) + Ok(RenameTable { old_name, new_name }) })?; Ok(Statement::RenameTable(rename_object_defs)) } else { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 12dd66105..de660aa66 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4028,19 +4028,17 @@ fn parse_alter_table() { #[test] fn parse_rename_table() { - let dialects = all_dialects_where(|d| d.supports_rename_table()); - - match dialects.verified_stmt("RENAME TABLE `test`.`test1` TO `test_db`.`test2`") { + match verified_stmt("RENAME TABLE test.test1 TO test_db.test2") { Statement::RenameTable(rename_object_defs) => { assert_eq!( - vec![RenameObjectDef { + vec![RenameTable { old_name: ObjectName(vec![ - Ident::with_quote('`', "test".to_string()), - Ident::with_quote('`', "test1".to_string()), + Ident::new("test".to_string()), + Ident::new("test1".to_string()), ]), new_name: ObjectName(vec![ - Ident::with_quote('`', "test_db".to_string()), - Ident::with_quote('`', "test2".to_string()), + Ident::new("test_db".to_string()), + Ident::new("test2".to_string()), ]), }], rename_object_defs @@ -4049,21 +4047,21 @@ fn parse_rename_table() { _ => unreachable!(), }; - match dialects.verified_stmt( + match verified_stmt( "RENAME TABLE old_table1 TO new_table1, old_table2 TO new_table2, old_table3 TO new_table3", ) { Statement::RenameTable(rename_object_defs) => { assert_eq!( vec![ - RenameObjectDef { + RenameTable { old_name: ObjectName(vec![Ident::new("old_table1".to_string())]), new_name: ObjectName(vec![Ident::new("new_table1".to_string())]), }, - RenameObjectDef { + RenameTable { old_name: ObjectName(vec![Ident::new("old_table2".to_string())]), new_name: ObjectName(vec![Ident::new("new_table2".to_string())]), }, - RenameObjectDef { + RenameTable { old_name: ObjectName(vec![Ident::new("old_table3".to_string())]), new_name: ObjectName(vec![Ident::new("new_table3".to_string())]), } @@ -4075,31 +4073,16 @@ fn parse_rename_table() { }; assert_eq!( - dialects - .parse_sql_statements("RENAME TABLE `old_table` TO new_table a") - .unwrap_err(), + parse_sql_statements("RENAME TABLE old_table TO new_table a").unwrap_err(), ParserError::ParserError("Expected: end of statement, found: a".to_string()) ); assert_eq!( - dialects - .parse_sql_statements("RENAME TABLE1 `old_table` TO new_table a") - .unwrap_err(), + parse_sql_statements("RENAME TABLE1 old_table TO new_table a").unwrap_err(), ParserError::ParserError( "Expected: KEYWORD `TABLE` after RENAME, found: TABLE1".to_string() ) ); - - let dialects = all_dialects_where(|d| !d.supports_rename_table()); - - assert_eq!( - dialects - .parse_sql_statements("RENAME TABLE `old_table` TO new_table") - .unwrap_err(), - ParserError::ParserError( - "Expected: KEYWORD `TABLE` after RENAME, found: TABLE".to_string() - ) - ); } #[test] From c94465966009dc1c621a8e756eee0ef8ea8100bb Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Sun, 29 Dec 2024 21:30:59 +0800 Subject: [PATCH 7/8] use more readable names --- src/ast/mod.rs | 8 ++------ src/parser/mod.rs | 4 ++-- tests/sqlparser_common.rs | 8 ++++---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 137500bfe..ed0ea4a6b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -4947,12 +4947,8 @@ impl fmt::Display for Statement { } Ok(()) } - Statement::RenameTable(rename_object_defs) => { - write!( - f, - "RENAME TABLE {}", - display_comma_separated(rename_object_defs) - ) + Statement::RenameTable(rename_tables) => { + write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables)) } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 9a444f7fb..a9c0a716d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1051,14 +1051,14 @@ impl<'a> Parser<'a> { pub fn parse_rename(&mut self) -> Result { if self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?; - let rename_object_defs = self.parse_comma_separated(|parser| { + let rename_tables = self.parse_comma_separated(|parser| { let old_name = parser.parse_object_name(false)?; parser.expect_keyword(Keyword::TO)?; let new_name = parser.parse_object_name(false)?; Ok(RenameTable { old_name, new_name }) })?; - Ok(Statement::RenameTable(rename_object_defs)) + Ok(Statement::RenameTable(rename_tables)) } else { self.expected("KEYWORD `TABLE` after RENAME", self.peek_token()) } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index de660aa66..799e45844 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -4029,7 +4029,7 @@ fn parse_alter_table() { #[test] fn parse_rename_table() { match verified_stmt("RENAME TABLE test.test1 TO test_db.test2") { - Statement::RenameTable(rename_object_defs) => { + Statement::RenameTable(rename_tables) => { assert_eq!( vec![RenameTable { old_name: ObjectName(vec![ @@ -4041,7 +4041,7 @@ fn parse_rename_table() { Ident::new("test2".to_string()), ]), }], - rename_object_defs + rename_tables ); } _ => unreachable!(), @@ -4050,7 +4050,7 @@ fn parse_rename_table() { match verified_stmt( "RENAME TABLE old_table1 TO new_table1, old_table2 TO new_table2, old_table3 TO new_table3", ) { - Statement::RenameTable(rename_object_defs) => { + Statement::RenameTable(rename_tables) => { assert_eq!( vec![ RenameTable { @@ -4066,7 +4066,7 @@ fn parse_rename_table() { new_name: ObjectName(vec![Ident::new("new_table3".to_string())]), } ], - rename_object_defs + rename_tables ); } _ => unreachable!(), From 9a7b4866ed6656f53280bfbb92b6cc9848d126a8 Mon Sep 17 00:00:00 2001 From: Ifeanyi Ubah Date: Wed, 1 Jan 2025 21:53:17 +0100 Subject: [PATCH 8/8] Apply suggestions from code review --- src/parser/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a9c0a716d..3b39f890f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -547,7 +547,6 @@ impl<'a> Parser<'a> { // `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html Keyword::PRAGMA => self.parse_pragma(), Keyword::UNLOAD => self.parse_unload(), - // `RENAME TABLE` is mysql specific https://dev.mysql.com/doc/refman/9.1/en/rename-table.html Keyword::RENAME => self.parse_rename(), // `INSTALL` is duckdb specific https://duckdb.org/docs/extensions/overview Keyword::INSTALL if dialect_of!(self is DuckDbDialect | GenericDialect) => { @@ -1047,7 +1046,6 @@ impl<'a> Parser<'a> { } /// Parses a `RENAME TABLE` statement. See [Statement::RenameTable] - /// see pub fn parse_rename(&mut self) -> Result { if self.peek_keyword(Keyword::TABLE) { self.expect_keyword(Keyword::TABLE)?;