Skip to content

Commit 7bafe13

Browse files
Snowflake: Add DESC[RIBE] EXTERNAL VOLUME
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5d653a2 commit 7bafe13

4 files changed

Lines changed: 96 additions & 6 deletions

File tree

‎src/ast/mod.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4608,6 +4608,11 @@ pub enum Statement {
46084608
comment: Option<String>,
46094609
},
46104610
/// ```sql
4611+
/// DESC[RIBE] EXTERNAL VOLUME <name>
4612+
/// ```
4613+
/// See <https://docs.snowflake.com/en/sql-reference/sql/desc-external-volume>
4614+
DescribeExternalVolume(DescribeExternalVolume),
4615+
/// ```sql
46114616
/// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
46124617
/// [ [ WITH ] <property> = <value> [ ... ] ]
46134618
/// ```
@@ -6344,6 +6349,7 @@ impl fmt::Display for Statement {
63446349
}
63456350
Ok(())
63466351
}
6352+
Statement::DescribeExternalVolume(s) => write!(f, "{s}"),
63476353
Statement::CreateWarehouse(s) => write!(f, "{s}"),
63486354
Statement::CopyIntoSnowflake {
63496355
kind,
@@ -11180,6 +11186,26 @@ pub struct ShowObjects {
1118011186
pub show_options: ShowStatementOptions,
1118111187
}
1118211188

11189+
/// ```sql
11190+
/// DESC[RIBE] EXTERNAL VOLUME <name>
11191+
/// ```
11192+
/// See <https://docs.snowflake.com/en/sql-reference/sql/desc-external-volume>
11193+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11194+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11195+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11196+
pub struct DescribeExternalVolume {
11197+
/// The keyword used, `DESC` or `DESCRIBE`.
11198+
pub describe_alias: DescribeAlias,
11199+
/// External volume name.
11200+
pub name: ObjectName,
11201+
}
11202+
11203+
impl fmt::Display for DescribeExternalVolume {
11204+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11205+
write!(f, "{} EXTERNAL VOLUME {}", self.describe_alias, self.name)
11206+
}
11207+
}
11208+
1118311209
/// MSSQL's json null clause
1118411210
///
1118511211
/// ```plaintext
@@ -12675,6 +12701,12 @@ impl From<CreateUser> for Statement {
1267512701
}
1267612702
}
1267712703

12704+
impl From<DescribeExternalVolume> for Statement {
12705+
fn from(d: DescribeExternalVolume) -> Self {
12706+
Self::DescribeExternalVolume(d)
12707+
}
12708+
}
12709+
1267812710
impl From<CreateWarehouse> for Statement {
1267912711
fn from(c: CreateWarehouse) -> Self {
1268012712
Self::CreateWarehouse(c)

‎src/ast/spans.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ impl Spanned for Statement {
524524
Statement::Vacuum(..) => Span::empty(),
525525
Statement::AlterUser(..) => Span::empty(),
526526
Statement::Reset(..) => Span::empty(),
527+
Statement::DescribeExternalVolume(..) => Span::empty(),
527528
}
528529
}
529530
}

‎src/dialect/snowflake.rs‎

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ use crate::ast::helpers::stmt_data_loading::{
2929
use crate::ast::{
3030
AlterTable, AlterTableOperation, AlterTableType, CatalogSyncNamespaceMode, ColumnOption,
3131
ColumnPolicy, ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTable,
32-
CreateTableLikeKind, DollarQuotedString, Ident, IdentityParameters, IdentityProperty,
33-
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, InitializeKind,
34-
Insert, MultiTableInsertIntoClause, MultiTableInsertType, MultiTableInsertValue,
35-
MultiTableInsertValues, MultiTableInsertWhenClause, ObjectName, ObjectNamePart,
36-
RefreshModeKind, RowAccessPolicy, ShowObjects, SqlOption, Statement, StorageLifecyclePolicy,
37-
StorageSerializationPolicy, TableObject, TagsColumnOption, Value, WrappedCollection,
32+
CreateTableLikeKind, DescribeAlias, DescribeExternalVolume, DollarQuotedString, Ident,
33+
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
34+
IdentityPropertyOrder, InitializeKind, Insert, MultiTableInsertIntoClause,
35+
MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues,
36+
MultiTableInsertWhenClause, ObjectName, ObjectNamePart, RefreshModeKind, RowAccessPolicy,
37+
ShowObjects, SqlOption, Statement, StorageLifecyclePolicy, StorageSerializationPolicy,
38+
TableObject, TagsColumnOption, Value, WrappedCollection,
3839
};
3940
use crate::dialect::{Dialect, Precedence};
4041
use crate::keywords::Keyword;
@@ -308,6 +309,20 @@ impl Dialect for SnowflakeDialect {
308309
return Some(parse_alter_session(parser, set));
309310
}
310311

312+
if let Some(kw) = parser.parse_one_of_keywords(&[Keyword::DESC, Keyword::DESCRIBE]) {
313+
if parser.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
314+
// DESC[RIBE] EXTERNAL VOLUME
315+
let describe_alias = if kw == Keyword::DESC {
316+
DescribeAlias::Desc
317+
} else {
318+
DescribeAlias::Describe
319+
};
320+
return Some(parse_describe_external_volume(describe_alias, parser));
321+
}
322+
// not EXTERNAL VOLUME — put back DESC/DESCRIBE
323+
parser.prev_token();
324+
}
325+
311326
if parser.parse_keyword(Keyword::CREATE) {
312327
// possibly CREATE STAGE
313328
//[ OR REPLACE ]
@@ -2018,3 +2033,16 @@ fn parse_multi_table_insert_when_clauses(
20182033

20192034
Ok((when_clauses, else_clause))
20202035
}
2036+
2037+
/// Parse `DESC[RIBE] EXTERNAL VOLUME <name>`
2038+
fn parse_describe_external_volume(
2039+
describe_alias: DescribeAlias,
2040+
parser: &mut Parser,
2041+
) -> Result<Statement, ParserError> {
2042+
let name = parser.parse_object_name(false)?;
2043+
Ok(DescribeExternalVolume {
2044+
describe_alias,
2045+
name,
2046+
}
2047+
.into())
2048+
}

‎tests/sqlparser_snowflake.rs‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5071,3 +5071,32 @@ fn test_stage_name_delimiters() {
50715071
ParserError::ParserError("Expected: stage name identifier, found: .".to_string()),
50725072
);
50735073
}
5074+
5075+
#[test]
5076+
fn test_describe_external_volume() {
5077+
match snowflake().verified_stmt("DESCRIBE EXTERNAL VOLUME my_vol") {
5078+
Statement::DescribeExternalVolume(DescribeExternalVolume {
5079+
describe_alias,
5080+
name,
5081+
}) => {
5082+
assert_eq!(DescribeAlias::Describe, describe_alias);
5083+
assert_eq!("my_vol", name.to_string());
5084+
}
5085+
_ => unreachable!(),
5086+
}
5087+
}
5088+
5089+
#[test]
5090+
fn test_desc_external_volume() {
5091+
// The DESC spelling is preserved on round-trip.
5092+
match snowflake().verified_stmt("DESC EXTERNAL VOLUME my_vol") {
5093+
Statement::DescribeExternalVolume(DescribeExternalVolume {
5094+
describe_alias,
5095+
name,
5096+
}) => {
5097+
assert_eq!(DescribeAlias::Desc, describe_alias);
5098+
assert_eq!("my_vol", name.to_string());
5099+
}
5100+
_ => unreachable!(),
5101+
}
5102+
}

0 commit comments

Comments
 (0)