Skip to content

Commit 7efa686

Browse files
authored
Extend snowflake grant options support (#1794)
1 parent 776b10a commit 7efa686

File tree

4 files changed

+126
-19
lines changed

4 files changed

+126
-19
lines changed

src/ast/mod.rs

+50-5
Original file line numberDiff line numberDiff line change
@@ -6079,10 +6079,10 @@ pub enum Action {
60796079
ManageReleases,
60806080
ManageVersions,
60816081
Modify {
6082-
modify_type: ActionModifyType,
6082+
modify_type: Option<ActionModifyType>,
60836083
},
60846084
Monitor {
6085-
monitor_type: ActionMonitorType,
6085+
monitor_type: Option<ActionMonitorType>,
60866086
},
60876087
Operate,
60886088
OverrideShareRestrictions,
@@ -6115,7 +6115,7 @@ impl fmt::Display for Action {
61156115
match self {
61166116
Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
61176117
Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6118-
Action::ApplyBudget => f.write_str("APPLY BUDGET")?,
6118+
Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
61196119
Action::AttachListing => f.write_str("ATTACH LISTING")?,
61206120
Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
61216121
Action::Audit => f.write_str("AUDIT")?,
@@ -6143,8 +6143,18 @@ impl fmt::Display for Action {
61436143
Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
61446144
Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
61456145
Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6146-
Action::Modify { modify_type } => write!(f, "MODIFY {modify_type}")?,
6147-
Action::Monitor { monitor_type } => write!(f, "MONITOR {monitor_type}")?,
6146+
Action::Modify { modify_type } => {
6147+
write!(f, "MODIFY")?;
6148+
if let Some(modify_type) = modify_type {
6149+
write!(f, " {modify_type}")?;
6150+
}
6151+
}
6152+
Action::Monitor { monitor_type } => {
6153+
write!(f, "MONITOR")?;
6154+
if let Some(monitor_type) = monitor_type {
6155+
write!(f, " {monitor_type}")?
6156+
}
6157+
}
61486158
Action::Operate => f.write_str("OPERATE")?,
61496159
Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
61506160
Action::Ownership => f.write_str("OWNERSHIP")?,
@@ -6462,6 +6472,20 @@ pub enum GrantObjects {
64626472
Warehouses(Vec<ObjectName>),
64636473
/// Grant privileges on specific integrations
64646474
Integrations(Vec<ObjectName>),
6475+
/// Grant privileges on resource monitors
6476+
ResourceMonitors(Vec<ObjectName>),
6477+
/// Grant privileges on users
6478+
Users(Vec<ObjectName>),
6479+
/// Grant privileges on compute pools
6480+
ComputePools(Vec<ObjectName>),
6481+
/// Grant privileges on connections
6482+
Connections(Vec<ObjectName>),
6483+
/// Grant privileges on failover groups
6484+
FailoverGroup(Vec<ObjectName>),
6485+
/// Grant privileges on replication group
6486+
ReplicationGroup(Vec<ObjectName>),
6487+
/// Grant privileges on external volumes
6488+
ExternalVolumes(Vec<ObjectName>),
64656489
}
64666490

64676491
impl fmt::Display for GrantObjects {
@@ -6502,6 +6526,27 @@ impl fmt::Display for GrantObjects {
65026526
display_comma_separated(schemas)
65036527
)
65046528
}
6529+
GrantObjects::ResourceMonitors(objects) => {
6530+
write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
6531+
}
6532+
GrantObjects::Users(objects) => {
6533+
write!(f, "USER {}", display_comma_separated(objects))
6534+
}
6535+
GrantObjects::ComputePools(objects) => {
6536+
write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
6537+
}
6538+
GrantObjects::Connections(objects) => {
6539+
write!(f, "CONNECTION {}", display_comma_separated(objects))
6540+
}
6541+
GrantObjects::FailoverGroup(objects) => {
6542+
write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
6543+
}
6544+
GrantObjects::ReplicationGroup(objects) => {
6545+
write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
6546+
}
6547+
GrantObjects::ExternalVolumes(objects) => {
6548+
write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
6549+
}
65056550
}
65066551
}
65076552
}

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ define_keywords!(
738738
REPLICATION,
739739
RESET,
740740
RESOLVE,
741+
RESOURCE,
741742
RESPECT,
742743
RESTART,
743744
RESTRICT,

src/parser/mod.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -12875,6 +12875,26 @@ impl<'a> Parser<'a> {
1287512875
Some(GrantObjects::AllSequencesInSchema {
1287612876
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1287712877
})
12878+
} else if self.parse_keywords(&[Keyword::RESOURCE, Keyword::MONITOR]) {
12879+
Some(GrantObjects::ResourceMonitors(self.parse_comma_separated(
12880+
|p| p.parse_object_name_with_wildcards(false, true),
12881+
)?))
12882+
} else if self.parse_keywords(&[Keyword::COMPUTE, Keyword::POOL]) {
12883+
Some(GrantObjects::ComputePools(self.parse_comma_separated(
12884+
|p| p.parse_object_name_with_wildcards(false, true),
12885+
)?))
12886+
} else if self.parse_keywords(&[Keyword::FAILOVER, Keyword::GROUP]) {
12887+
Some(GrantObjects::FailoverGroup(self.parse_comma_separated(
12888+
|p| p.parse_object_name_with_wildcards(false, true),
12889+
)?))
12890+
} else if self.parse_keywords(&[Keyword::REPLICATION, Keyword::GROUP]) {
12891+
Some(GrantObjects::ReplicationGroup(self.parse_comma_separated(
12892+
|p| p.parse_object_name_with_wildcards(false, true),
12893+
)?))
12894+
} else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
12895+
Some(GrantObjects::ExternalVolumes(self.parse_comma_separated(
12896+
|p| p.parse_object_name_with_wildcards(false, true),
12897+
)?))
1287812898
} else {
1287912899
let object_type = self.parse_one_of_keywords(&[
1288012900
Keyword::SEQUENCE,
@@ -12888,6 +12908,8 @@ impl<'a> Parser<'a> {
1288812908
Keyword::VIEW,
1288912909
Keyword::WAREHOUSE,
1289012910
Keyword::INTEGRATION,
12911+
Keyword::USER,
12912+
Keyword::CONNECTION,
1289112913
]);
1289212914
let objects =
1289312915
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
@@ -12898,6 +12920,8 @@ impl<'a> Parser<'a> {
1289812920
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
1289912921
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
1290012922
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
12923+
Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
12924+
Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
1290112925
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
1290212926
_ => unreachable!(),
1290312927
}
@@ -12983,10 +13007,10 @@ impl<'a> Parser<'a> {
1298313007
let manage_type = self.parse_action_manage_type()?;
1298413008
Ok(Action::Manage { manage_type })
1298513009
} else if self.parse_keyword(Keyword::MODIFY) {
12986-
let modify_type = self.parse_action_modify_type()?;
13010+
let modify_type = self.parse_action_modify_type();
1298713011
Ok(Action::Modify { modify_type })
1298813012
} else if self.parse_keyword(Keyword::MONITOR) {
12989-
let monitor_type = self.parse_action_monitor_type()?;
13013+
let monitor_type = self.parse_action_monitor_type();
1299013014
Ok(Action::Monitor { monitor_type })
1299113015
} else if self.parse_keyword(Keyword::OPERATE) {
1299213016
Ok(Action::Operate)
@@ -13127,29 +13151,29 @@ impl<'a> Parser<'a> {
1312713151
}
1312813152
}
1312913153

13130-
fn parse_action_modify_type(&mut self) -> Result<ActionModifyType, ParserError> {
13154+
fn parse_action_modify_type(&mut self) -> Option<ActionModifyType> {
1313113155
if self.parse_keywords(&[Keyword::LOG, Keyword::LEVEL]) {
13132-
Ok(ActionModifyType::LogLevel)
13156+
Some(ActionModifyType::LogLevel)
1313313157
} else if self.parse_keywords(&[Keyword::TRACE, Keyword::LEVEL]) {
13134-
Ok(ActionModifyType::TraceLevel)
13158+
Some(ActionModifyType::TraceLevel)
1313513159
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::LOG, Keyword::LEVEL]) {
13136-
Ok(ActionModifyType::SessionLogLevel)
13160+
Some(ActionModifyType::SessionLogLevel)
1313713161
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::TRACE, Keyword::LEVEL]) {
13138-
Ok(ActionModifyType::SessionTraceLevel)
13162+
Some(ActionModifyType::SessionTraceLevel)
1313913163
} else {
13140-
self.expected("GRANT MODIFY type", self.peek_token())
13164+
None
1314113165
}
1314213166
}
1314313167

13144-
fn parse_action_monitor_type(&mut self) -> Result<ActionMonitorType, ParserError> {
13168+
fn parse_action_monitor_type(&mut self) -> Option<ActionMonitorType> {
1314513169
if self.parse_keyword(Keyword::EXECUTION) {
13146-
Ok(ActionMonitorType::Execution)
13170+
Some(ActionMonitorType::Execution)
1314713171
} else if self.parse_keyword(Keyword::SECURITY) {
13148-
Ok(ActionMonitorType::Security)
13172+
Some(ActionMonitorType::Security)
1314913173
} else if self.parse_keyword(Keyword::USAGE) {
13150-
Ok(ActionMonitorType::Usage)
13174+
Some(ActionMonitorType::Usage)
1315113175
} else {
13152-
self.expected("GRANT MONITOR type", self.peek_token())
13176+
None
1315313177
}
1315413178
}
1315513179

tests/sqlparser_snowflake.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -3357,7 +3357,7 @@ fn test_timetravel_at_before() {
33573357
}
33583358

33593359
#[test]
3360-
fn test_grant_account_privileges() {
3360+
fn test_grant_account_global_privileges() {
33613361
let privileges = vec![
33623362
"ALL",
33633363
"ALL PRIVILEGES",
@@ -3462,6 +3462,43 @@ fn test_grant_account_privileges() {
34623462
}
34633463
}
34643464

3465+
#[test]
3466+
fn test_grant_account_object_privileges() {
3467+
let privileges = vec![
3468+
"ALL",
3469+
"ALL PRIVILEGES",
3470+
"APPLYBUDGET",
3471+
"MODIFY",
3472+
"MONITOR",
3473+
"USAGE",
3474+
"OPERATE",
3475+
];
3476+
3477+
let objects_types = vec![
3478+
"USER",
3479+
"RESOURCE MONITOR",
3480+
"WAREHOUSE",
3481+
"COMPUTE POOL",
3482+
"DATABASE",
3483+
"INTEGRATION",
3484+
"CONNECTION",
3485+
"FAILOVER GROUP",
3486+
"REPLICATION GROUP",
3487+
"EXTERNAL VOLUME",
3488+
];
3489+
3490+
let with_grant_options = vec!["", " WITH GRANT OPTION"];
3491+
3492+
for t in &objects_types {
3493+
for p in &privileges {
3494+
for wgo in &with_grant_options {
3495+
let sql = format!("GRANT {p} ON {t} obj1 TO ROLE role1{wgo}");
3496+
snowflake_and_generic().verified_stmt(&sql);
3497+
}
3498+
}
3499+
}
3500+
}
3501+
34653502
#[test]
34663503
fn test_grant_role_to() {
34673504
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO ROLE r2");

0 commit comments

Comments
 (0)