Support ALTER TABLE ... SET LOCATION (#1154)

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
Jonathan Lehto 2024-03-01 14:05:05 -05:00 committed by GitHub
parent 6f090e5547
commit 991dbab755
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 59 additions and 7 deletions

View file

@ -2001,6 +2001,7 @@ pub enum Statement {
if_exists: bool,
only: bool,
operations: Vec<AlterTableOperation>,
location: Option<HiveSetLocation>,
},
/// ```sql
/// ALTER INDEX
@ -3249,12 +3250,10 @@ impl fmt::Display for Statement {
}
}
if *external {
write!(
f,
" STORED AS {} LOCATION '{}'",
file_format.as_ref().unwrap(),
location.as_ref().unwrap()
)?;
if let Some(file_format) = &file_format {
write!(f, " STORED AS {file_format}")?;
}
write!(f, " LOCATION '{}'", location.as_ref().unwrap())?;
}
if !table_properties.is_empty() {
write!(
@ -3504,6 +3503,7 @@ impl fmt::Display for Statement {
if_exists,
only,
operations,
location,
} => {
write!(f, "ALTER TABLE ")?;
if *if_exists {
@ -3516,7 +3516,11 @@ impl fmt::Display for Statement {
f,
"{name} {operations}",
operations = display_comma_separated(operations)
)
)?;
if let Some(loc) = location {
write!(f, " {loc}")?
}
Ok(())
}
Statement::AlterIndex { name, operation } => {
write!(f, "ALTER INDEX {name} {operation}")
@ -5840,6 +5844,23 @@ impl fmt::Display for LockTableType {
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct HiveSetLocation {
pub has_set: bool,
pub location: Ident,
}
impl fmt::Display for HiveSetLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.has_set {
write!(f, "SET ")?;
}
write!(f, "LOCATION {}", self.location)
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -5529,11 +5529,26 @@ impl<'a> Parser<'a> {
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
let table_name = self.parse_object_name(false)?;
let operations = self.parse_comma_separated(Parser::parse_alter_table_operation)?;
let mut location = None;
if self.parse_keyword(Keyword::LOCATION) {
location = Some(HiveSetLocation {
has_set: false,
location: self.parse_identifier(false)?,
});
} else if self.parse_keywords(&[Keyword::SET, Keyword::LOCATION]) {
location = Some(HiveSetLocation {
has_set: true,
location: self.parse_identifier(false)?,
});
}
Ok(Statement::AlterTable {
name: table_name,
if_exists,
only,
operations,
location,
})
}
Keyword::INDEX => {

View file

@ -256,6 +256,7 @@ pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTa
if_exists,
only: is_only,
operations,
location: _,
} => {
assert_eq!(name.to_string(), expected_name);
assert!(!if_exists);
@ -265,6 +266,7 @@ pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTa
_ => panic!("Expected ALTER TABLE statement"),
}
}
pub fn alter_table_op(stmt: Statement) -> AlterTableOperation {
alter_table_op_with_name(stmt, "tab")
}

View file

@ -124,6 +124,19 @@ fn test_alter_partition() {
hive().verified_stmt(alter);
}
#[test]
fn test_alter_with_location() {
let alter =
"ALTER TABLE db.table PARTITION (a = 2) RENAME TO PARTITION (a = 1) LOCATION 's3://...'";
hive().verified_stmt(alter);
}
#[test]
fn test_alter_with_set_location() {
let alter = "ALTER TABLE db.table PARTITION (a = 2) RENAME TO PARTITION (a = 1) SET LOCATION 's3://...'";
hive().verified_stmt(alter);
}
#[test]
fn test_add_partition() {
let add = "ALTER TABLE db.table ADD IF NOT EXISTS PARTITION (a = 'asdf', b = 2)";

View file

@ -677,6 +677,7 @@ fn parse_alter_table_add_columns() {
if_exists,
only,
operations,
location: _,
} => {
assert_eq!(name.to_string(), "tab");
assert!(if_exists);