Skip to content

Commit 1c6d2b6

Browse files
wugeeriffyio
authored andcommitted
Add support for MYSQL's RENAME TABLE (apache#1616)
Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
1 parent a9774ac commit 1c6d2b6

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

src/ast/mod.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3431,6 +3431,13 @@ pub enum Statement {
34313431
partitioned: Option<Vec<Expr>>,
34323432
table_format: Option<HiveLoadDataFormat>,
34333433
},
3434+
/// ```sql
3435+
/// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
3436+
/// ```
3437+
/// Renames one or more tables
3438+
///
3439+
/// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
3440+
RenameTable(Vec<RenameTable>),
34343441
}
34353442

34363443
impl fmt::Display for Statement {
@@ -4988,6 +4995,9 @@ impl fmt::Display for Statement {
49884995
}
49894996
Ok(())
49904997
}
4998+
Statement::RenameTable(rename_tables) => {
4999+
write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
5000+
}
49915001
}
49925002
}
49935003
}
@@ -7690,6 +7700,22 @@ impl Display for JsonNullClause {
76907700
}
76917701
}
76927702

7703+
/// rename object definition
7704+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7705+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7706+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7707+
pub struct RenameTable {
7708+
pub old_name: ObjectName,
7709+
pub new_name: ObjectName,
7710+
}
7711+
7712+
impl fmt::Display for RenameTable {
7713+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7714+
write!(f, "{} TO {}", self.old_name, self.new_name)?;
7715+
Ok(())
7716+
}
7717+
}
7718+
76937719
#[cfg(test)]
76947720
mod tests {
76957721
use super::*;

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ impl Spanned for Statement {
492492
Statement::NOTIFY { .. } => Span::empty(),
493493
Statement::LoadData { .. } => Span::empty(),
494494
Statement::UNLISTEN { .. } => Span::empty(),
495+
Statement::RenameTable { .. } => Span::empty(),
495496
}
496497
}
497498
}

src/parser/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ impl<'a> Parser<'a> {
595595
// `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html
596596
Keyword::PRAGMA => self.parse_pragma(),
597597
Keyword::UNLOAD => self.parse_unload(),
598+
Keyword::RENAME => self.parse_rename(),
598599
// `INSTALL` is duckdb specific https://duckdb.org/docs/extensions/overview
599600
Keyword::INSTALL if dialect_of!(self is DuckDbDialect | GenericDialect) => {
600601
self.parse_install()
@@ -1085,6 +1086,23 @@ impl<'a> Parser<'a> {
10851086
Ok(Statement::NOTIFY { channel, payload })
10861087
}
10871088

1089+
/// Parses a `RENAME TABLE` statement. See [Statement::RenameTable]
1090+
pub fn parse_rename(&mut self) -> Result<Statement, ParserError> {
1091+
if self.peek_keyword(Keyword::TABLE) {
1092+
self.expect_keyword(Keyword::TABLE)?;
1093+
let rename_tables = self.parse_comma_separated(|parser| {
1094+
let old_name = parser.parse_object_name(false)?;
1095+
parser.expect_keyword(Keyword::TO)?;
1096+
let new_name = parser.parse_object_name(false)?;
1097+
1098+
Ok(RenameTable { old_name, new_name })
1099+
})?;
1100+
Ok(Statement::RenameTable(rename_tables))
1101+
} else {
1102+
self.expected("KEYWORD `TABLE` after RENAME", self.peek_token())
1103+
}
1104+
}
1105+
10881106
// Tries to parse an expression by matching the specified word to known keywords that have a special meaning in the dialect.
10891107
// Returns `None if no match is found.
10901108
fn parse_expr_prefix_by_reserved_word(

tests/sqlparser_common.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4134,6 +4134,65 @@ fn parse_alter_table() {
41344134
}
41354135
}
41364136

4137+
#[test]
4138+
fn parse_rename_table() {
4139+
match verified_stmt("RENAME TABLE test.test1 TO test_db.test2") {
4140+
Statement::RenameTable(rename_tables) => {
4141+
assert_eq!(
4142+
vec![RenameTable {
4143+
old_name: ObjectName(vec![
4144+
Ident::new("test".to_string()),
4145+
Ident::new("test1".to_string()),
4146+
]),
4147+
new_name: ObjectName(vec![
4148+
Ident::new("test_db".to_string()),
4149+
Ident::new("test2".to_string()),
4150+
]),
4151+
}],
4152+
rename_tables
4153+
);
4154+
}
4155+
_ => unreachable!(),
4156+
};
4157+
4158+
match verified_stmt(
4159+
"RENAME TABLE old_table1 TO new_table1, old_table2 TO new_table2, old_table3 TO new_table3",
4160+
) {
4161+
Statement::RenameTable(rename_tables) => {
4162+
assert_eq!(
4163+
vec![
4164+
RenameTable {
4165+
old_name: ObjectName(vec![Ident::new("old_table1".to_string())]),
4166+
new_name: ObjectName(vec![Ident::new("new_table1".to_string())]),
4167+
},
4168+
RenameTable {
4169+
old_name: ObjectName(vec![Ident::new("old_table2".to_string())]),
4170+
new_name: ObjectName(vec![Ident::new("new_table2".to_string())]),
4171+
},
4172+
RenameTable {
4173+
old_name: ObjectName(vec![Ident::new("old_table3".to_string())]),
4174+
new_name: ObjectName(vec![Ident::new("new_table3".to_string())]),
4175+
}
4176+
],
4177+
rename_tables
4178+
);
4179+
}
4180+
_ => unreachable!(),
4181+
};
4182+
4183+
assert_eq!(
4184+
parse_sql_statements("RENAME TABLE old_table TO new_table a").unwrap_err(),
4185+
ParserError::ParserError("Expected: end of statement, found: a".to_string())
4186+
);
4187+
4188+
assert_eq!(
4189+
parse_sql_statements("RENAME TABLE1 old_table TO new_table a").unwrap_err(),
4190+
ParserError::ParserError(
4191+
"Expected: KEYWORD `TABLE` after RENAME, found: TABLE1".to_string()
4192+
)
4193+
);
4194+
}
4195+
41374196
#[test]
41384197
fn test_alter_table_with_on_cluster() {
41394198
match all_dialects()

0 commit comments

Comments
 (0)