This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new bef86dd6 Snowflake: parse CREATE WAREHOUSE (#2388)
bef86dd6 is described below
commit bef86dd6826ea0d87143f59403b12aa3a588bd4f
Author: sabir-akhadov-localstack <[email protected]>
AuthorDate: Tue Jul 21 12:15:04 2026 +0200
Snowflake: parse CREATE WAREHOUSE (#2388)
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
src/ast/mod.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++
src/ast/spans.rs | 1 +
src/parser/mod.rs | 24 ++++++++++++++++++--
tests/sqlparser_common.rs | 13 +++++++++++
4 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index b2777ccb..b1a81c76 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -4536,6 +4536,14 @@ pub enum Statement {
comment: Option<String>,
},
/// ```sql
+ /// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
+ /// [ [ WITH ] <property> = <value> [ ... ] ]
+ /// ```
+ /// Snowflake-specific statement to create a virtual warehouse.
+ ///
+ /// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
+ CreateWarehouse(CreateWarehouse),
+ /// ```sql
/// ASSERT <condition> [AS <message>]
/// ```
Assert {
@@ -6261,6 +6269,7 @@ impl fmt::Display for Statement {
}
Ok(())
}
+ Statement::CreateWarehouse(s) => write!(f, "{s}"),
Statement::CopyIntoSnowflake {
kind,
into,
@@ -8587,6 +8596,8 @@ pub enum ObjectType {
User,
/// A stream.
Stream,
+ /// A warehouse.
+ Warehouse,
}
impl fmt::Display for ObjectType {
@@ -8605,6 +8616,7 @@ impl fmt::Display for ObjectType {
ObjectType::Type => "TYPE",
ObjectType::User => "USER",
ObjectType::Stream => "STREAM",
+ ObjectType::Warehouse => "WAREHOUSE",
})
}
}
@@ -11610,6 +11622,45 @@ impl fmt::Display for CreateUser {
}
}
+/// ```sql
+/// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
+/// [ [ WITH ] <property> = <value> [ ... ] ]
+/// ```
+/// Snowflake-specific statement to create a virtual warehouse.
+///
+/// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateWarehouse {
+ /// `OR REPLACE` flag.
+ pub or_replace: bool,
+ /// `IF NOT EXISTS` flag.
+ pub if_not_exists: bool,
+ /// Warehouse name.
+ pub name: ObjectName,
+ /// Warehouse properties and parameters (e.g. `WAREHOUSE_SIZE = 'XSMALL'`).
+ pub options: KeyValueOptions,
+}
+
+impl fmt::Display for CreateWarehouse {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "CREATE")?;
+ if self.or_replace {
+ write!(f, " OR REPLACE")?;
+ }
+ write!(f, " WAREHOUSE")?;
+ if self.if_not_exists {
+ write!(f, " IF NOT EXISTS")?;
+ }
+ write!(f, " {}", self.name)?;
+ if !self.options.options.is_empty() {
+ write!(f, " {}", self.options)?;
+ }
+ Ok(())
+ }
+}
+
/// Modifies the properties of a user
///
/// [Snowflake
Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
@@ -12481,6 +12532,12 @@ impl From<CreateUser> for Statement {
}
}
+impl From<CreateWarehouse> for Statement {
+ fn from(c: CreateWarehouse) -> Self {
+ Self::CreateWarehouse(c)
+ }
+}
+
impl From<VacuumStatement> for Statement {
fn from(v: VacuumStatement) -> Self {
Self::Vacuum(v)
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index aaad33a5..09a40f66 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -461,6 +461,7 @@ impl Spanned for Statement {
Statement::CreateMacro { .. } => Span::empty(),
Statement::CreateStage { .. } => Span::empty(),
Statement::CreateFileFormat { .. } => Span::empty(),
+ Statement::CreateWarehouse(..) => Span::empty(),
Statement::Assert { .. } => Span::empty(),
Statement::Grant { .. } => Span::empty(),
Statement::Deny { .. } => Span::empty(),
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 6a2292f3..6df5cf30 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -5283,9 +5283,11 @@ impl<'a> Parser<'a> {
self.parse_create_secret(or_replace, temporary, persistent)
} else if self.parse_keyword(Keyword::USER) {
self.parse_create_user(or_replace).map(Into::into)
+ } else if self.parse_keyword(Keyword::WAREHOUSE) {
+ self.parse_create_warehouse(or_replace).map(Into::into)
} else if or_replace {
self.expected_ref(
- "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after
CREATE OR REPLACE",
+ "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION or
WAREHOUSE after CREATE OR REPLACE",
self.peek_token_ref(),
)
} else if self.parse_keyword(Keyword::EXTENSION) {
@@ -5430,6 +5432,22 @@ impl<'a> Parser<'a> {
})
}
+ /// Parse a `CREATE WAREHOUSE` statement.
+ ///
+ /// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
+ fn parse_create_warehouse(&mut self, or_replace: bool) ->
Result<CreateWarehouse, ParserError> {
+ let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT,
Keyword::EXISTS]);
+ let name = self.parse_object_name(false)?;
+ let _ = self.parse_keyword(Keyword::WITH);
+ let options = self.parse_key_value_options(false, &[])?;
+ Ok(CreateWarehouse {
+ or_replace,
+ if_not_exists,
+ name,
+ options,
+ })
+ }
+
/// See [DuckDB
Docs](https://duckdb.org/docs/sql/statements/create_secret.html) for more
details.
pub fn parse_create_secret(
&mut self,
@@ -7581,6 +7599,8 @@ impl<'a> Parser<'a> {
ObjectType::User
} else if self.parse_keyword(Keyword::STREAM) {
ObjectType::Stream
+ } else if self.parse_keyword(Keyword::WAREHOUSE) {
+ ObjectType::Warehouse
} else if self.parse_keyword(Keyword::FUNCTION) {
return self.parse_drop_function().map(Into::into);
} else if self.parse_keyword(Keyword::POLICY) {
@@ -7608,7 +7628,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 or USER after DROP",
+ "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",
self.peek_token_ref(),
);
};
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index ff3d8079..edd9a9e3 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -8888,6 +8888,19 @@ fn parse_drop_user() {
verified_stmt("DROP USER IF EXISTS u1");
}
+#[test]
+fn parse_create_warehouse() {
+ verified_stmt("CREATE WAREHOUSE my_wh");
+ verified_stmt("CREATE OR REPLACE WAREHOUSE IF NOT EXISTS my_wh");
+ verified_stmt("CREATE WAREHOUSE my_wh WAREHOUSE_SIZE='XSMALL'
AUTO_SUSPEND=60");
+ one_statement_parses_to(
+ "CREATE WAREHOUSE my_wh WITH WAREHOUSE_SIZE = 'XSMALL' AUTO_SUSPEND =
60",
+ "CREATE WAREHOUSE my_wh WAREHOUSE_SIZE='XSMALL' AUTO_SUSPEND=60",
+ );
+ verified_stmt("DROP WAREHOUSE my_wh");
+ verified_stmt("DROP WAREHOUSE IF EXISTS my_wh");
+}
+
#[test]
fn parse_invalid_subquery_without_parens() {
let res = parse_sql_statements("SELECT SELECT 1 FROM bar WHERE 1=1 FROM
baz");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]