diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 668c520e5..612cc9be4 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6533,10 +6533,16 @@ 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]); + let mut 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()?; + // Snowflake also documents `COPY GRANTS` *after* the column list; accept + // either position, but not both. + // + if !copy_grants { + copy_grants = self.parse_keywords(&[Keyword::COPY, Keyword::GRANTS]); + } let mut options = CreateTableOptions::None; let with_options = self.parse_options(Keyword::WITH)?; if !with_options.is_empty() { diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 790bf1515..992129e4e 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -4764,6 +4764,28 @@ fn test_snowflake_create_view_copy_grants() { ); } +#[test] +fn test_snowflake_create_view_copy_grants_after_columns() { + let cases = [ + ( + "CREATE OR REPLACE VIEW v (a, b) COPY GRANTS AS SELECT a, b FROM t", + "CREATE OR REPLACE VIEW v COPY GRANTS (a, b) AS SELECT a, b FROM t", + ), + ( + "CREATE OR REPLACE SECURE VIEW v (a, b) COPY GRANTS AS SELECT a, b FROM t", + "CREATE OR REPLACE SECURE VIEW v COPY GRANTS (a, b) AS SELECT a, b FROM t", + ), + ( + "CREATE MATERIALIZED VIEW v (a) COPY GRANTS AS SELECT a FROM t", + "CREATE MATERIALIZED VIEW v COPY GRANTS (a) AS SELECT a FROM t", + ), + ]; + for (sql, parsed) in cases { + snowflake().one_statement_parses_to(sql, parsed); + } + snowflake().verified_stmt("CREATE OR REPLACE VIEW v (a) AS SELECT a FROM t"); +} + #[test] fn test_snowflake_identifier_function() { // Using IDENTIFIER to reference a column