Skip to content

Commit f1c44cd

Browse files
committed
Add SECURE keyword for views in Snowflake
1 parent b660a3b commit f1c44cd

File tree

6 files changed

+48
-2
lines changed

6 files changed

+48
-2
lines changed

src/ast/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3255,6 +3255,9 @@ pub enum Statement {
32553255
or_alter: bool,
32563256
or_replace: bool,
32573257
materialized: bool,
3258+
/// Snowflake: SECURE view modifier
3259+
/// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3260+
secure: bool,
32583261
/// View name
32593262
name: ObjectName,
32603263
/// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
@@ -5105,6 +5108,7 @@ impl fmt::Display for Statement {
51055108
columns,
51065109
query,
51075110
materialized,
5111+
secure,
51085112
options,
51095113
cluster_by,
51105114
comment,
@@ -5126,7 +5130,7 @@ impl fmt::Display for Statement {
51265130
}
51275131
write!(
51285132
f,
5129-
"{materialized}{temporary}VIEW {if_not_and_name}{to}",
5133+
"{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
51305134
if_not_and_name = if *if_not_exists {
51315135
if *name_before_not_exists {
51325136
format!("{name} IF NOT EXISTS")
@@ -5136,6 +5140,7 @@ impl fmt::Display for Statement {
51365140
} else {
51375141
format!("{name}")
51385142
},
5143+
secure = if *secure { "SECURE " } else { "" },
51395144
materialized = if *materialized { "MATERIALIZED " } else { "" },
51405145
temporary = if *temporary { "TEMPORARY " } else { "" },
51415146
to = to

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ impl Spanned for Statement {
391391
or_alter: _,
392392
or_replace: _,
393393
materialized: _,
394+
secure: _,
394395
name,
395396
columns,
396397
query,

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ define_keywords!(
814814
SECONDARY_ENGINE_ATTRIBUTE,
815815
SECONDS,
816816
SECRET,
817+
SECURE,
817818
SECURITY,
818819
SEED,
819820
SELECT,

src/parser/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4713,7 +4713,10 @@ impl<'a> Parser<'a> {
47134713
let create_view_params = self.parse_create_view_params()?;
47144714
if self.parse_keyword(Keyword::TABLE) {
47154715
self.parse_create_table(or_replace, temporary, global, transient)
4716-
} else if self.parse_keyword(Keyword::MATERIALIZED) || self.parse_keyword(Keyword::VIEW) {
4716+
} else if self.parse_keyword(Keyword::MATERIALIZED)
4717+
|| self.parse_keyword(Keyword::VIEW)
4718+
|| (dialect_of!(self is SnowflakeDialect) && self.parse_keyword(Keyword::SECURE))
4719+
{
47174720
self.prev_token();
47184721
self.parse_create_view(or_alter, or_replace, temporary, create_view_params)
47194722
} else if self.parse_keyword(Keyword::POLICY) {
@@ -5834,6 +5837,7 @@ impl<'a> Parser<'a> {
58345837
temporary: bool,
58355838
create_view_params: Option<CreateViewParams>,
58365839
) -> Result<Statement, ParserError> {
5840+
let secure = self.parse_keyword(Keyword::SECURE);
58375841
let materialized = self.parse_keyword(Keyword::MATERIALIZED);
58385842
self.expect_keyword_is(Keyword::VIEW)?;
58395843
let allow_unquoted_hyphen = dialect_of!(self is BigQueryDialect);
@@ -5904,6 +5908,7 @@ impl<'a> Parser<'a> {
59045908
columns,
59055909
query,
59065910
materialized,
5911+
secure,
59075912
or_replace,
59085913
options,
59095914
cluster_by,

tests/sqlparser_common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8078,6 +8078,7 @@ fn parse_create_view() {
80788078
to,
80798079
params,
80808080
name_before_not_exists: _,
8081+
secure: _,
80818082
} => {
80828083
assert_eq!(or_alter, false);
80838084
assert_eq!("myschema.myview", name.to_string());
@@ -8147,6 +8148,7 @@ fn parse_create_view_with_columns() {
81478148
to,
81488149
params,
81498150
name_before_not_exists: _,
8151+
secure: _,
81508152
} => {
81518153
assert_eq!(or_alter, false);
81528154
assert_eq!("v", name.to_string());
@@ -8197,6 +8199,7 @@ fn parse_create_view_temporary() {
81978199
to,
81988200
params,
81998201
name_before_not_exists: _,
8202+
secure: _,
82008203
} => {
82018204
assert_eq!(or_alter, false);
82028205
assert_eq!("myschema.myview", name.to_string());
@@ -8237,6 +8240,7 @@ fn parse_create_or_replace_view() {
82378240
to,
82388241
params,
82398242
name_before_not_exists: _,
8243+
secure: _,
82408244
} => {
82418245
assert_eq!(or_alter, false);
82428246
assert_eq!("v", name.to_string());
@@ -8281,6 +8285,7 @@ fn parse_create_or_replace_materialized_view() {
82818285
to,
82828286
params,
82838287
name_before_not_exists: _,
8288+
secure: _,
82848289
} => {
82858290
assert_eq!(or_alter, false);
82868291
assert_eq!("v", name.to_string());
@@ -8321,6 +8326,7 @@ fn parse_create_materialized_view() {
83218326
to,
83228327
params,
83238328
name_before_not_exists: _,
8329+
secure: _,
83248330
} => {
83258331
assert_eq!(or_alter, false);
83268332
assert_eq!("myschema.myview", name.to_string());
@@ -8361,6 +8367,7 @@ fn parse_create_materialized_view_with_cluster_by() {
83618367
to,
83628368
params,
83638369
name_before_not_exists: _,
8370+
secure: _,
83648371
} => {
83658372
assert_eq!(or_alter, false);
83668373
assert_eq!("myschema.myview", name.to_string());

tests/sqlparser_snowflake.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ fn test_snowflake_create_table() {
4444
}
4545
}
4646

47+
#[test]
48+
fn parse_sf_create_secure_view_and_materialized_view() {
49+
for sql in [
50+
"CREATE SECURE VIEW v AS SELECT 1",
51+
"CREATE SECURE MATERIALIZED VIEW v AS SELECT 1",
52+
"CREATE OR REPLACE SECURE VIEW v AS SELECT 1",
53+
"CREATE OR REPLACE SECURE MATERIALIZED VIEW v AS SELECT 1",
54+
] {
55+
match snowflake().verified_stmt(sql) {
56+
Statement::CreateView {
57+
secure,
58+
materialized,
59+
..
60+
} => {
61+
assert!(secure);
62+
if sql.contains("MATERIALIZED") {
63+
assert!(materialized);
64+
} else {
65+
assert!(!materialized);
66+
}
67+
}
68+
_ => unreachable!(),
69+
}
70+
assert_eq!(snowflake().verified_stmt(sql).to_string(), sql);
71+
}
72+
}
73+
4774
#[test]
4875
fn test_snowflake_create_or_replace_table() {
4976
let sql = "CREATE OR REPLACE TABLE my_table (a number)";

0 commit comments

Comments
 (0)