From a941b00cf4f4d13bc937b2992bc00bb2a279d636 Mon Sep 17 00:00:00 2001 From: sabir-akhadov-localstack Date: Wed, 28 Oct 2026 09:14:12 +0100 Subject: [PATCH] Snowflake: Add DROP EXTERNAL VOLUME Co-Authored-By: Claude Opus 5.5 --- src/ast/mod.rs | 3 +++ src/parser/mod.rs | 4 +++- tests/sqlparser_snowflake.rs | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index d3ffdc2ab0..9689e3deac 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -8774,6 +8774,8 @@ pub enum ObjectType { User, /// A stream. Stream, + /// A Snowflake external volume. + ExternalVolume, /// A warehouse. Warehouse, } @@ -8794,6 +8796,7 @@ impl fmt::Display for ObjectType { ObjectType::Type => "TYPE", ObjectType::User => "USER", ObjectType::Stream => "STREAM", + ObjectType::ExternalVolume => "EXTERNAL VOLUME", ObjectType::Warehouse => "WAREHOUSE", }) } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d09c601eb9..66b61bb5bd 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -8103,6 +8103,8 @@ impl<'a> Parser<'a> { ObjectType::User } else if self.parse_keyword(Keyword::STREAM) { ObjectType::Stream + } else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) { + ObjectType::ExternalVolume } else if self.parse_keyword(Keyword::WAREHOUSE) { ObjectType::Warehouse } else if self.parse_keyword(Keyword::FUNCTION) { @@ -8132,7 +8134,7 @@ impl<'a> Parser<'a> { }; } else { return self.expected_ref( - "COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW, USER or WAREHOUSE after DROP", + "COLLATION, CONNECTOR, DATABASE, EXTENSION, EXTERNAL VOLUME, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW, USER or WAREHOUSE after DROP", self.peek_token_ref(), ); }; diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 5e3cbc8e01..62842e5ffb 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -5042,3 +5042,40 @@ fn test_stage_name_delimiters() { ParserError::ParserError("Expected: stage name identifier, found: .".to_string()), ); } + +#[test] +fn test_drop_external_volume() { + match snowflake().verified_stmt("DROP EXTERNAL VOLUME my_vol") { + Statement::Drop { + object_type, + if_exists, + names, + .. + } => { + assert_eq!(ObjectType::ExternalVolume, object_type); + assert!(!if_exists); + assert_eq!("my_vol", names[0].to_string()); + } + _ => unreachable!(), + } + let err = snowflake() + .parse_sql_statements("DROP EXTERNAL my_vol") + .unwrap_err() + .to_string(); + assert!(err.contains("EXTERNAL VOLUME"), "{err}"); +} + +#[test] +fn test_drop_external_volume_if_exists() { + match snowflake().verified_stmt("DROP EXTERNAL VOLUME IF EXISTS my_vol") { + Statement::Drop { + object_type, + if_exists, + .. + } => { + assert_eq!(ObjectType::ExternalVolume, object_type); + assert!(if_exists); + } + _ => unreachable!(), + } +}