Skip to content

Snowflake: Add EXTERNAL VOLUME DDL#2397

Open
sabir-akhadov-localstack wants to merge 4 commits into
apache:mainfrom
localstack:pr/05-external-volume
Open

Snowflake: Add EXTERNAL VOLUME DDL#2397
sabir-akhadov-localstack wants to merge 4 commits into
apache:mainfrom
localstack:pr/05-external-volume

Conversation

@sabir-akhadov-localstack

@sabir-akhadov-localstack sabir-akhadov-localstack commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Snowflake's external-volume DDL did not parse. This adds CREATE [OR REPLACE] EXTERNAL VOLUME [IF NOT EXISTS], ALTER, DROP, DESCRIBE/DESC and SHOW EXTERNAL VOLUMES.

Example that failed before:

CREATE EXTERNAL VOLUME my_vol STORAGE_LOCATIONS = (
    (NAME = 'loc1' STORAGE_PROVIDER = 'S3' STORAGE_BASE_URL = 's3://bucket/path/'));

Each storage location is a parenthesized key-value option list parsed generically into the existing KeyValueOptions, so fields (including the nested ENCRYPTION = (...) list) may appear in any order, matching real Snowflake. Only an empty location is rejected; semantic checks such as the required STORAGE_BASE_URL or duplicate fields are left to the consumer, in line with the parser's permissive stance. The trailing ALLOW_WRITES and COMMENT properties are accepted in either order. All statements round-trip, including the DESC vs DESCRIBE spelling.

See the Snowflake CREATE EXTERNAL VOLUME docs.

🤖 Generated with Claude Code

Snowflake's external-volume statements did not parse. This adds
CREATE [OR REPLACE] EXTERNAL VOLUME [IF NOT EXISTS], ALTER, DROP,
DESCRIBE/DESC and SHOW EXTERNAL VOLUMES.

Example that failed before:

    CREATE EXTERNAL VOLUME my_vol STORAGE_LOCATIONS = (
        (NAME = 'loc1' STORAGE_PROVIDER = 'S3'
         STORAGE_BASE_URL = 's3://bucket/path/'))

Storage locations accept STORAGE_BASE_URL, STORAGE_AWS_ROLE_ARN,
STORAGE_AWS_EXTERNAL_ID and ENCRYPTION in any order after NAME and
STORAGE_PROVIDER, matching real Snowflake; required fields and
duplicates are validated after parsing. All statements round-trip.
sabir-akhadov-localstack and others added 2 commits July 3, 2026 10:32
Address review feedback by building on existing infrastructure instead of
bespoke AST:

- Parse storage locations (and the nested ENCRYPTION clause) via
  Parser::parse_key_value_options, the same path CREATE STAGE uses. Storage
  locations are now Vec<KeyValueOptions>; the ExternalVolumeStorageLocation
  and ExternalVolumeEncryption structs and their hand-written Display and
  parser code are removed. Parsing is syntax-only, so field order is
  preserved and semantic checks (required STORAGE_BASE_URL, duplicate
  fields) are left to the consumer.
- Route DROP EXTERNAL VOLUME through the generic Statement::Drop machinery
  via a new ObjectType::ExternalVolume, matching how STAGE/STREAM are
  handled, and drop the dedicated DropExternalVolume statement variant.
- Use expect_keyword_is instead of expect_keyword to match the file's
  convention, and remove the now-unused option-name keywords.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sabir-akhadov-localstack sabir-akhadov-localstack marked this pull request as ready for review July 3, 2026 15:41
…mpty locations

Address review findings: preserve the DESC/DESCRIBE spelling via a
DescribeAlias field so DESC EXTERNAL VOLUME round-trips verbatim like
every other DESC form; accept ALLOW_WRITES and COMMENT in either order,
matching parse_create_database; reject an empty storage location
(STORAGE_LOCATIONS = (()) previously parsed while () was rejected) in
both CREATE and ALTER ADD via a shared helper; and use
parse_comma_separated instead of a hand-rolled comma loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant