Skip to content

Commit 94ea206

Browse files
wugeeriffyio
andauthored
Add support for MYSQL's RENAME TABLE (apache#1616)
Co-authored-by: Ifeanyi Ubah <[email protected]>
1 parent 3bad04e commit 94ea206

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
@@ -3413,6 +3413,13 @@ pub enum Statement {
34133413
partitioned: Option<Vec<Expr>>,
34143414
table_format: Option<HiveLoadDataFormat>,
34153415
},
3416+
/// ```sql
3417+
/// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
3418+
/// ```
3419+
/// Renames one or more tables
3420+
///
3421+
/// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
3422+
RenameTable(Vec<RenameTable>),
34163423
}
34173424

34183425
impl fmt::Display for Statement {
@@ -4970,6 +4977,9 @@ impl fmt::Display for Statement {
49704977
}
49714978
Ok(())
49724979
}
4980+
Statement::RenameTable(rename_tables) => {
4981+
write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
4982+
}
49734983
}
49744984
}
49754985
}
@@ -7672,6 +7682,22 @@ impl Display for JsonNullClause {
76727682
}
76737683
}
76747684

7685+
/// rename object definition
7686+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7687+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7688+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7689+
pub struct RenameTable {
7690+
pub old_name: ObjectName,
7691+
pub new_name: ObjectName,
7692+
}
7693+
7694+
impl fmt::Display for RenameTable {
7695+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7696+
write!(f, "{} TO {}", self.old_name, self.new_name)?;
7697+
Ok(())
7698+
}
7699+
}
7700+
76757701
#[cfg(test)]
76767702
mod tests {
76777703
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
@@ -4133,6 +4133,65 @@ fn parse_alter_table() {
41334133
}
41344134
}
41354135

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

0 commit comments

Comments
 (0)