Skip to content

Commit 5327f0c

Browse files
authored
Add ICEBERG keyword support to ALTER TABLE statement (#1869)
1 parent 394a534 commit 5327f0c

File tree

7 files changed

+64
-38
lines changed

7 files changed

+64
-38
lines changed

src/ast/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,6 +3281,9 @@ pub enum Statement {
32813281
/// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
32823282
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
32833283
on_cluster: Option<Ident>,
3284+
/// Snowflake "ICEBERG" clause for Iceberg tables
3285+
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3286+
iceberg: bool,
32843287
},
32853288
/// ```sql
32863289
/// ALTER INDEX
@@ -3405,7 +3408,7 @@ pub enum Statement {
34053408
purge: bool,
34063409
/// MySQL-specific "TEMPORARY" keyword
34073410
temporary: bool,
3408-
/// MySQL-specific drop index syntax, which requires table specification
3411+
/// MySQL-specific drop index syntax, which requires table specification
34093412
/// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
34103413
table: Option<ObjectName>,
34113414
},
@@ -5139,8 +5142,14 @@ impl fmt::Display for Statement {
51395142
operations,
51405143
location,
51415144
on_cluster,
5145+
iceberg,
51425146
} => {
5143-
write!(f, "ALTER TABLE ")?;
5147+
if *iceberg {
5148+
write!(f, "ALTER ICEBERG TABLE ")?;
5149+
} else {
5150+
write!(f, "ALTER TABLE ")?;
5151+
}
5152+
51445153
if *if_exists {
51455154
write!(f, "IF EXISTS ")?;
51465155
}

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ impl Spanned for Statement {
431431
operations,
432432
location: _,
433433
on_cluster,
434+
iceberg: _,
434435
} => union_spans(
435436
core::iter::once(name.span())
436437
.chain(operations.iter().map(|i| i.span()))

src/parser/mod.rs

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8893,38 +8893,15 @@ impl<'a> Parser<'a> {
88938893
Keyword::ROLE,
88948894
Keyword::POLICY,
88958895
Keyword::CONNECTOR,
8896+
Keyword::ICEBERG,
88968897
])?;
88978898
match object_type {
88988899
Keyword::VIEW => self.parse_alter_view(),
88998900
Keyword::TYPE => self.parse_alter_type(),
8900-
Keyword::TABLE => {
8901-
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
8902-
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
8903-
let table_name = self.parse_object_name(false)?;
8904-
let on_cluster = self.parse_optional_on_cluster()?;
8905-
let operations = self.parse_comma_separated(Parser::parse_alter_table_operation)?;
8906-
8907-
let mut location = None;
8908-
if self.parse_keyword(Keyword::LOCATION) {
8909-
location = Some(HiveSetLocation {
8910-
has_set: false,
8911-
location: self.parse_identifier()?,
8912-
});
8913-
} else if self.parse_keywords(&[Keyword::SET, Keyword::LOCATION]) {
8914-
location = Some(HiveSetLocation {
8915-
has_set: true,
8916-
location: self.parse_identifier()?,
8917-
});
8918-
}
8919-
8920-
Ok(Statement::AlterTable {
8921-
name: table_name,
8922-
if_exists,
8923-
only,
8924-
operations,
8925-
location,
8926-
on_cluster,
8927-
})
8901+
Keyword::TABLE => self.parse_alter_table(false),
8902+
Keyword::ICEBERG => {
8903+
self.expect_keyword(Keyword::TABLE)?;
8904+
self.parse_alter_table(true)
89288905
}
89298906
Keyword::INDEX => {
89308907
let index_name = self.parse_object_name(false)?;
@@ -8952,6 +8929,38 @@ impl<'a> Parser<'a> {
89528929
}
89538930
}
89548931

8932+
/// Parse a [Statement::AlterTable]
8933+
pub fn parse_alter_table(&mut self, iceberg: bool) -> Result<Statement, ParserError> {
8934+
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
8935+
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
8936+
let table_name = self.parse_object_name(false)?;
8937+
let on_cluster = self.parse_optional_on_cluster()?;
8938+
let operations = self.parse_comma_separated(Parser::parse_alter_table_operation)?;
8939+
8940+
let mut location = None;
8941+
if self.parse_keyword(Keyword::LOCATION) {
8942+
location = Some(HiveSetLocation {
8943+
has_set: false,
8944+
location: self.parse_identifier()?,
8945+
});
8946+
} else if self.parse_keywords(&[Keyword::SET, Keyword::LOCATION]) {
8947+
location = Some(HiveSetLocation {
8948+
has_set: true,
8949+
location: self.parse_identifier()?,
8950+
});
8951+
}
8952+
8953+
Ok(Statement::AlterTable {
8954+
name: table_name,
8955+
if_exists,
8956+
only,
8957+
operations,
8958+
location,
8959+
on_cluster,
8960+
iceberg,
8961+
})
8962+
}
8963+
89558964
pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
89568965
let name = self.parse_object_name(false)?;
89578966
let columns = self.parse_parenthesized_column_list(Optional, false)?;

src/test_utils.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,10 +345,12 @@ pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTa
345345
operations,
346346
on_cluster: _,
347347
location: _,
348+
iceberg,
348349
} => {
349350
assert_eq!(name.to_string(), expected_name);
350351
assert!(!if_exists);
351352
assert!(!is_only);
353+
assert!(!iceberg);
352354
only(operations)
353355
}
354356
_ => panic!("Expected ALTER TABLE statement"),

tests/sqlparser_mysql.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,11 +2507,13 @@ fn parse_alter_table_add_column() {
25072507
if_exists,
25082508
only,
25092509
operations,
2510+
iceberg,
25102511
location: _,
25112512
on_cluster: _,
25122513
} => {
25132514
assert_eq!(name.to_string(), "tab");
25142515
assert!(!if_exists);
2516+
assert!(!iceberg);
25152517
assert!(!only);
25162518
assert_eq!(
25172519
operations,
@@ -2536,8 +2538,7 @@ fn parse_alter_table_add_column() {
25362538
if_exists,
25372539
only,
25382540
operations,
2539-
location: _,
2540-
on_cluster: _,
2541+
..
25412542
} => {
25422543
assert_eq!(name.to_string(), "tab");
25432544
assert!(!if_exists);
@@ -2574,8 +2575,7 @@ fn parse_alter_table_add_columns() {
25742575
if_exists,
25752576
only,
25762577
operations,
2577-
location: _,
2578-
on_cluster: _,
2578+
..
25792579
} => {
25802580
assert_eq!(name.to_string(), "tab");
25812581
assert!(!if_exists);

tests/sqlparser_postgres.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,7 @@ fn parse_alter_table_add_columns() {
834834
if_exists,
835835
only,
836836
operations,
837-
location: _,
838-
on_cluster: _,
837+
..
839838
} => {
840839
assert_eq!(name.to_string(), "tab");
841840
assert!(if_exists);
@@ -915,8 +914,7 @@ fn parse_alter_table_owner_to() {
915914
if_exists: _,
916915
only: _,
917916
operations,
918-
location: _,
919-
on_cluster: _,
917+
..
920918
} => {
921919
assert_eq!(name.to_string(), "tab");
922920
assert_eq!(

tests/sqlparser_snowflake.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,13 @@ fn test_alter_table_clustering() {
15911591
snowflake_and_generic().verified_stmt("ALTER TABLE tbl RESUME RECLUSTER");
15921592
}
15931593

1594+
#[test]
1595+
fn test_alter_iceberg_table() {
1596+
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl DROP CLUSTERING KEY");
1597+
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl SUSPEND RECLUSTER");
1598+
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl RESUME RECLUSTER");
1599+
}
1600+
15941601
#[test]
15951602
fn test_drop_stage() {
15961603
match snowflake_and_generic().verified_stmt("DROP STAGE s1") {

0 commit comments

Comments
 (0)