This is an automated email from the ASF dual-hosted git repository.
github-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 b6003eb9 Fixed COPY GRANTS clause parsing for snowflake (#2267)
b6003eb9 is described below
commit b6003eb98e721943c711672571d7cf252c42ae2b
Author: Andriy Romanov <[email protected]>
AuthorDate: Mon Mar 9 02:27:03 2026 -0700
Fixed COPY GRANTS clause parsing for snowflake (#2267)
---
src/ast/ddl.rs | 6 ++++++
src/parser/mod.rs | 2 ++
tests/sqlparser_common.rs | 6 ++++++
tests/sqlparser_snowflake.rs | 11 +++++++++++
4 files changed, 25 insertions(+)
diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index 6bea28cb..d6da8368 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -4293,6 +4293,9 @@ pub struct CreateView {
pub if_not_exists: bool,
/// if true, has SQLite `TEMP` or `TEMPORARY` clause
<https://www.sqlite.org/lang_createview.html>
pub temporary: bool,
+ /// Snowflake: `COPY GRANTS` clause
+ /// <https://docs.snowflake.com/en/sql-reference/sql/create-view>
+ pub copy_grants: bool,
/// if not None, has Clickhouse `TO` clause, specify the table into which
to insert results
///
<https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
pub to: Option<ObjectName>,
@@ -4336,6 +4339,9 @@ impl fmt::Display for CreateView {
.map(|to| format!(" TO {to}"))
.unwrap_or_default()
)?;
+ if self.copy_grants {
+ write!(f, " COPY GRANTS")?;
+ }
if !self.columns.is_empty() {
write!(f, " ({})", display_comma_separated(&self.columns))?;
}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index eaaa95ec..f9432f86 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -6375,6 +6375,7 @@ impl<'a> Parser<'a> {
let name_before_not_exists = !if_not_exists_first
&& self.parse_keywords(&[Keyword::IF, Keyword::NOT,
Keyword::EXISTS]);
let if_not_exists = if_not_exists_first || name_before_not_exists;
+ let copy_grants = self.parse_keywords(&[Keyword::COPY,
Keyword::GRANTS]);
// Many dialects support `OR ALTER` right after `CREATE`, but we don't
(yet).
// ANSI SQL and Postgres support RECURSIVE here, but we don't support
it either.
let columns = self.parse_view_columns()?;
@@ -6442,6 +6443,7 @@ impl<'a> Parser<'a> {
with_no_schema_binding,
if_not_exists,
temporary,
+ copy_grants,
to,
params: create_view_params,
name_before_not_exists,
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index a59e3b96..08fb6107 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -8317,6 +8317,7 @@ fn parse_create_view() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("myschema.myview", name.to_string());
@@ -8435,6 +8436,7 @@ fn parse_create_view_temporary() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("myschema.myview", name.to_string());
@@ -8476,6 +8478,7 @@ fn parse_create_or_replace_view() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("v", name.to_string());
@@ -8521,6 +8524,7 @@ fn parse_create_or_replace_materialized_view() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("v", name.to_string());
@@ -8562,6 +8566,7 @@ fn parse_create_materialized_view() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("myschema.myview", name.to_string());
@@ -8603,6 +8608,7 @@ fn parse_create_materialized_view_with_cluster_by() {
params,
name_before_not_exists: _,
secure: _,
+ copy_grants: _,
}) => {
assert_eq!(or_alter, false);
assert_eq!("myschema.myview", name.to_string());
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index 022c644a..265f8a9a 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -4671,6 +4671,17 @@ fn
test_snowflake_create_view_with_composite_policy_name() {
snowflake().verified_stmt(create_view_with_tag);
}
+#[test]
+fn test_snowflake_create_view_copy_grants() {
+ snowflake().verified_stmt("CREATE OR REPLACE VIEW bla COPY GRANTS AS
(SELECT * FROM source)");
+ snowflake()
+ .verified_stmt("CREATE OR REPLACE SECURE VIEW bla COPY GRANTS AS
(SELECT * FROM source)");
+ // COPY GRANTS with column list
+ snowflake().verified_stmt(
+ "CREATE OR REPLACE VIEW bla COPY GRANTS (a, b) AS (SELECT a, b FROM
source)",
+ );
+}
+
#[test]
fn test_snowflake_identifier_function() {
// Using IDENTIFIER to reference a column
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]