Fixing ALTER EXTERNAL TABLE queries for snowflake

This commit is contained in:
Andriy Romanov 2025-12-03 11:39:25 -08:00
parent 5a3b63bf41
commit 0f4a063e2d
4 changed files with 59 additions and 9 deletions

View file

@ -3880,8 +3880,11 @@ pub enum AlterTableType {
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
Iceberg,
/// Dynamic table type
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-dynamic-table>
Dynamic,
/// External table type
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-external-table>
External,
}
/// ALTER TABLE statement
@ -3911,6 +3914,7 @@ impl fmt::Display for AlterTable {
match &self.table_type {
Some(AlterTableType::Iceberg) => write!(f, "ALTER ICEBERG TABLE ")?,
Some(AlterTableType::Dynamic) => write!(f, "ALTER DYNAMIC TABLE ")?,
Some(AlterTableType::External) => write!(f, "ALTER EXTERNAL TABLE ")?,
None => write!(f, "ALTER TABLE ")?,
}

View file

@ -221,6 +221,11 @@ impl Dialect for SnowflakeDialect {
return Some(parse_alter_dynamic_table(parser));
}
if parser.parse_keywords(&[Keyword::ALTER, Keyword::EXTERNAL, Keyword::TABLE]) {
// ALTER EXTERNAL TABLE
return Some(parse_alter_external_table(parser));
}
if parser.parse_keywords(&[Keyword::ALTER, Keyword::SESSION]) {
// ALTER SESSION
let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {
@ -649,6 +654,37 @@ fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserErr
}))
}
/// Parse snowflake alter external table.
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-external-table>
fn parse_alter_external_table(parser: &mut Parser) -> Result<Statement, ParserError> {
let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let table_name = parser.parse_object_name(true)?;
// Parse the operation (REFRESH for now, can be extended)
let operation = if parser.parse_keyword(Keyword::REFRESH) {
AlterTableOperation::Refresh
} else {
return parser.expected("REFRESH after ALTER EXTERNAL TABLE", parser.peek_token());
};
let end_token = if parser.peek_token_ref().token == Token::SemiColon {
parser.peek_token_ref().clone()
} else {
parser.get_current_token().clone()
};
Ok(Statement::AlterTable(AlterTable {
name: table_name,
if_exists,
only: false,
operations: vec![operation],
location: None,
on_cluster: None,
table_type: Some(AlterTableType::External),
end_token: AttachedToken(end_token),
}))
}
/// Parse snowflake alter session.
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {

View file

@ -9778,6 +9778,7 @@ impl<'a> Parser<'a> {
Keyword::POLICY,
Keyword::CONNECTOR,
Keyword::ICEBERG,
Keyword::EXTERNAL,
Keyword::SCHEMA,
Keyword::USER,
])?;
@ -9789,10 +9790,14 @@ impl<'a> Parser<'a> {
}
Keyword::VIEW => self.parse_alter_view(),
Keyword::TYPE => self.parse_alter_type(),
Keyword::TABLE => self.parse_alter_table(false),
Keyword::TABLE => self.parse_alter_table(None),
Keyword::ICEBERG => {
self.expect_keyword(Keyword::TABLE)?;
self.parse_alter_table(true)
self.parse_alter_table(Some(AlterTableType::Iceberg))
}
Keyword::EXTERNAL => {
self.expect_keyword(Keyword::TABLE)?;
self.parse_alter_table(Some(AlterTableType::External))
}
Keyword::INDEX => {
let index_name = self.parse_object_name(false)?;
@ -9822,7 +9827,10 @@ impl<'a> Parser<'a> {
}
/// Parse a [Statement::AlterTable]
pub fn parse_alter_table(&mut self, iceberg: bool) -> Result<Statement, ParserError> {
pub fn parse_alter_table(
&mut self,
table_type: Option<AlterTableType>,
) -> Result<Statement, ParserError> {
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
let table_name = self.parse_object_name(false)?;
@ -9855,11 +9863,7 @@ impl<'a> Parser<'a> {
operations,
location,
on_cluster,
table_type: if iceberg {
Some(AlterTableType::Iceberg)
} else {
None
},
table_type,
end_token: AttachedToken(end_token),
}
.into())

View file

@ -4635,3 +4635,9 @@ fn test_alter_dynamic_table() {
snowflake().verified_stmt("ALTER DYNAMIC TABLE my_dyn_table SUSPEND");
snowflake().verified_stmt("ALTER DYNAMIC TABLE my_dyn_table RESUME");
}
#[test]
fn test_alter_external_table() {
snowflake().verified_stmt("ALTER EXTERNAL TABLE some_table REFRESH");
snowflake().verified_stmt("ALTER EXTERNAL TABLE my_database.my_schema.my_external_table REFRESH");
}