mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
Add ICEBERG keyword support to ALTER TABLE statement (#1869)
This commit is contained in:
parent
394a534486
commit
5327f0ce13
7 changed files with 64 additions and 38 deletions
|
@ -3281,6 +3281,9 @@ pub enum Statement {
|
||||||
/// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
|
/// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
|
||||||
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
|
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
|
||||||
on_cluster: Option<Ident>,
|
on_cluster: Option<Ident>,
|
||||||
|
/// Snowflake "ICEBERG" clause for Iceberg tables
|
||||||
|
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
|
||||||
|
iceberg: bool,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// ALTER INDEX
|
/// ALTER INDEX
|
||||||
|
@ -5139,8 +5142,14 @@ impl fmt::Display for Statement {
|
||||||
operations,
|
operations,
|
||||||
location,
|
location,
|
||||||
on_cluster,
|
on_cluster,
|
||||||
|
iceberg,
|
||||||
} => {
|
} => {
|
||||||
|
if *iceberg {
|
||||||
|
write!(f, "ALTER ICEBERG TABLE ")?;
|
||||||
|
} else {
|
||||||
write!(f, "ALTER TABLE ")?;
|
write!(f, "ALTER TABLE ")?;
|
||||||
|
}
|
||||||
|
|
||||||
if *if_exists {
|
if *if_exists {
|
||||||
write!(f, "IF EXISTS ")?;
|
write!(f, "IF EXISTS ")?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,7 @@ impl Spanned for Statement {
|
||||||
operations,
|
operations,
|
||||||
location: _,
|
location: _,
|
||||||
on_cluster,
|
on_cluster,
|
||||||
|
iceberg: _,
|
||||||
} => union_spans(
|
} => union_spans(
|
||||||
core::iter::once(name.span())
|
core::iter::once(name.span())
|
||||||
.chain(operations.iter().map(|i| i.span()))
|
.chain(operations.iter().map(|i| i.span()))
|
||||||
|
|
|
@ -8893,11 +8893,44 @@ impl<'a> Parser<'a> {
|
||||||
Keyword::ROLE,
|
Keyword::ROLE,
|
||||||
Keyword::POLICY,
|
Keyword::POLICY,
|
||||||
Keyword::CONNECTOR,
|
Keyword::CONNECTOR,
|
||||||
|
Keyword::ICEBERG,
|
||||||
])?;
|
])?;
|
||||||
match object_type {
|
match object_type {
|
||||||
Keyword::VIEW => self.parse_alter_view(),
|
Keyword::VIEW => self.parse_alter_view(),
|
||||||
Keyword::TYPE => self.parse_alter_type(),
|
Keyword::TYPE => self.parse_alter_type(),
|
||||||
Keyword::TABLE => {
|
Keyword::TABLE => self.parse_alter_table(false),
|
||||||
|
Keyword::ICEBERG => {
|
||||||
|
self.expect_keyword(Keyword::TABLE)?;
|
||||||
|
self.parse_alter_table(true)
|
||||||
|
}
|
||||||
|
Keyword::INDEX => {
|
||||||
|
let index_name = self.parse_object_name(false)?;
|
||||||
|
let operation = if self.parse_keyword(Keyword::RENAME) {
|
||||||
|
if self.parse_keyword(Keyword::TO) {
|
||||||
|
let index_name = self.parse_object_name(false)?;
|
||||||
|
AlterIndexOperation::RenameIndex { index_name }
|
||||||
|
} else {
|
||||||
|
return self.expected("TO after RENAME", self.peek_token());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return self.expected("RENAME after ALTER INDEX", self.peek_token());
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Statement::AlterIndex {
|
||||||
|
name: index_name,
|
||||||
|
operation,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Keyword::ROLE => self.parse_alter_role(),
|
||||||
|
Keyword::POLICY => self.parse_alter_policy(),
|
||||||
|
Keyword::CONNECTOR => self.parse_alter_connector(),
|
||||||
|
// unreachable because expect_one_of_keywords used above
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a [Statement::AlterTable]
|
||||||
|
pub fn parse_alter_table(&mut self, iceberg: bool) -> Result<Statement, ParserError> {
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
|
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
|
||||||
let table_name = self.parse_object_name(false)?;
|
let table_name = self.parse_object_name(false)?;
|
||||||
|
@ -8924,33 +8957,9 @@ impl<'a> Parser<'a> {
|
||||||
operations,
|
operations,
|
||||||
location,
|
location,
|
||||||
on_cluster,
|
on_cluster,
|
||||||
|
iceberg,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Keyword::INDEX => {
|
|
||||||
let index_name = self.parse_object_name(false)?;
|
|
||||||
let operation = if self.parse_keyword(Keyword::RENAME) {
|
|
||||||
if self.parse_keyword(Keyword::TO) {
|
|
||||||
let index_name = self.parse_object_name(false)?;
|
|
||||||
AlterIndexOperation::RenameIndex { index_name }
|
|
||||||
} else {
|
|
||||||
return self.expected("TO after RENAME", self.peek_token());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return self.expected("RENAME after ALTER INDEX", self.peek_token());
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Statement::AlterIndex {
|
|
||||||
name: index_name,
|
|
||||||
operation,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Keyword::ROLE => self.parse_alter_role(),
|
|
||||||
Keyword::POLICY => self.parse_alter_policy(),
|
|
||||||
Keyword::CONNECTOR => self.parse_alter_connector(),
|
|
||||||
// unreachable because expect_one_of_keywords used above
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
|
||||||
let name = self.parse_object_name(false)?;
|
let name = self.parse_object_name(false)?;
|
||||||
|
|
|
@ -345,10 +345,12 @@ pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTa
|
||||||
operations,
|
operations,
|
||||||
on_cluster: _,
|
on_cluster: _,
|
||||||
location: _,
|
location: _,
|
||||||
|
iceberg,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), expected_name);
|
assert_eq!(name.to_string(), expected_name);
|
||||||
assert!(!if_exists);
|
assert!(!if_exists);
|
||||||
assert!(!is_only);
|
assert!(!is_only);
|
||||||
|
assert!(!iceberg);
|
||||||
only(operations)
|
only(operations)
|
||||||
}
|
}
|
||||||
_ => panic!("Expected ALTER TABLE statement"),
|
_ => panic!("Expected ALTER TABLE statement"),
|
||||||
|
|
|
@ -2507,11 +2507,13 @@ fn parse_alter_table_add_column() {
|
||||||
if_exists,
|
if_exists,
|
||||||
only,
|
only,
|
||||||
operations,
|
operations,
|
||||||
|
iceberg,
|
||||||
location: _,
|
location: _,
|
||||||
on_cluster: _,
|
on_cluster: _,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), "tab");
|
assert_eq!(name.to_string(), "tab");
|
||||||
assert!(!if_exists);
|
assert!(!if_exists);
|
||||||
|
assert!(!iceberg);
|
||||||
assert!(!only);
|
assert!(!only);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
operations,
|
operations,
|
||||||
|
@ -2536,8 +2538,7 @@ fn parse_alter_table_add_column() {
|
||||||
if_exists,
|
if_exists,
|
||||||
only,
|
only,
|
||||||
operations,
|
operations,
|
||||||
location: _,
|
..
|
||||||
on_cluster: _,
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), "tab");
|
assert_eq!(name.to_string(), "tab");
|
||||||
assert!(!if_exists);
|
assert!(!if_exists);
|
||||||
|
@ -2574,8 +2575,7 @@ fn parse_alter_table_add_columns() {
|
||||||
if_exists,
|
if_exists,
|
||||||
only,
|
only,
|
||||||
operations,
|
operations,
|
||||||
location: _,
|
..
|
||||||
on_cluster: _,
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), "tab");
|
assert_eq!(name.to_string(), "tab");
|
||||||
assert!(!if_exists);
|
assert!(!if_exists);
|
||||||
|
|
|
@ -834,8 +834,7 @@ fn parse_alter_table_add_columns() {
|
||||||
if_exists,
|
if_exists,
|
||||||
only,
|
only,
|
||||||
operations,
|
operations,
|
||||||
location: _,
|
..
|
||||||
on_cluster: _,
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), "tab");
|
assert_eq!(name.to_string(), "tab");
|
||||||
assert!(if_exists);
|
assert!(if_exists);
|
||||||
|
@ -915,8 +914,7 @@ fn parse_alter_table_owner_to() {
|
||||||
if_exists: _,
|
if_exists: _,
|
||||||
only: _,
|
only: _,
|
||||||
operations,
|
operations,
|
||||||
location: _,
|
..
|
||||||
on_cluster: _,
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(name.to_string(), "tab");
|
assert_eq!(name.to_string(), "tab");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1591,6 +1591,13 @@ fn test_alter_table_clustering() {
|
||||||
snowflake_and_generic().verified_stmt("ALTER TABLE tbl RESUME RECLUSTER");
|
snowflake_and_generic().verified_stmt("ALTER TABLE tbl RESUME RECLUSTER");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_alter_iceberg_table() {
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl DROP CLUSTERING KEY");
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl SUSPEND RECLUSTER");
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl RESUME RECLUSTER");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_drop_stage() {
|
fn test_drop_stage() {
|
||||||
match snowflake_and_generic().verified_stmt("DROP STAGE s1") {
|
match snowflake_and_generic().verified_stmt("DROP STAGE s1") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue