Skip to content

Commit 660ef6b

Browse files
committed
Snowflake GRANT privileges on account objects
1 parent 10cf7c1 commit 660ef6b

File tree

4 files changed

+133
-19
lines changed

4 files changed

+133
-19
lines changed

src/ast/mod.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6001,10 +6001,10 @@ pub enum Action {
60016001
ManageReleases,
60026002
ManageVersions,
60036003
Modify {
6004-
modify_type: ActionModifyType,
6004+
modify_type: Option<ActionModifyType>,
60056005
},
60066006
Monitor {
6007-
monitor_type: ActionMonitorType,
6007+
monitor_type: Option<ActionMonitorType>,
60086008
},
60096009
Operate,
60106010
OverrideShareRestrictions,
@@ -6037,7 +6037,7 @@ impl fmt::Display for Action {
60376037
match self {
60386038
Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
60396039
Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6040-
Action::ApplyBudget => f.write_str("APPLY BUDGET")?,
6040+
Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
60416041
Action::AttachListing => f.write_str("ATTACH LISTING")?,
60426042
Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
60436043
Action::Audit => f.write_str("AUDIT")?,
@@ -6065,8 +6065,18 @@ impl fmt::Display for Action {
60656065
Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
60666066
Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
60676067
Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6068-
Action::Modify { modify_type } => write!(f, "MODIFY {modify_type}")?,
6069-
Action::Monitor { monitor_type } => write!(f, "MONITOR {monitor_type}")?,
6068+
Action::Modify { modify_type } => {
6069+
write!(f, "MODIFY")?;
6070+
if let Some(modify_type) = modify_type {
6071+
write!(f, " {modify_type}")?;
6072+
}
6073+
}
6074+
Action::Monitor { monitor_type } => {
6075+
write!(f, "MONITOR")?;
6076+
if let Some(monitor_type) = monitor_type {
6077+
write!(f, " {monitor_type}")?
6078+
}
6079+
}
60706080
Action::Operate => f.write_str("OPERATE")?,
60716081
Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
60726082
Action::Ownership => f.write_str("OWNERSHIP")?,
@@ -6384,6 +6394,20 @@ pub enum GrantObjects {
63846394
Warehouses(Vec<ObjectName>),
63856395
/// Grant privileges on specific integrations
63866396
Integrations(Vec<ObjectName>),
6397+
/// Grant privileges on resource monitors
6398+
ResourceMonitors(Vec<ObjectName>),
6399+
/// Grant privileges on users
6400+
Users(Vec<ObjectName>),
6401+
/// Grant privileges on compute pools
6402+
ComputePools(Vec<ObjectName>),
6403+
/// Grant privileges on connections
6404+
Connections(Vec<ObjectName>),
6405+
/// Grant privileges on failover groups
6406+
FailoverGroup(Vec<ObjectName>),
6407+
/// Grant privileges on replication group
6408+
ReplicationGroup(Vec<ObjectName>),
6409+
/// Grant privileges on external volumes
6410+
ExternalVolumes(Vec<ObjectName>),
63876411
}
63886412

63896413
impl fmt::Display for GrantObjects {
@@ -6424,6 +6448,27 @@ impl fmt::Display for GrantObjects {
64246448
display_comma_separated(schemas)
64256449
)
64266450
}
6451+
GrantObjects::ResourceMonitors(objects) => {
6452+
write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
6453+
}
6454+
GrantObjects::Users(objects) => {
6455+
write!(f, "USER {}", display_comma_separated(objects))
6456+
}
6457+
GrantObjects::ComputePools(objects) => {
6458+
write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
6459+
}
6460+
GrantObjects::Connections(objects) => {
6461+
write!(f, "CONNECTION {}", display_comma_separated(objects))
6462+
}
6463+
GrantObjects::FailoverGroup(objects) => {
6464+
write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
6465+
}
6466+
GrantObjects::ReplicationGroup(objects) => {
6467+
write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
6468+
}
6469+
GrantObjects::ExternalVolumes(objects) => {
6470+
write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
6471+
}
64276472
}
64286473
}
64296474
}

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ define_keywords!(
736736
REPLICATION,
737737
RESET,
738738
RESOLVE,
739+
RESOURCE,
739740
RESPECT,
740741
RESTART,
741742
RESTRICT,

src/parser/mod.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12821,6 +12821,26 @@ impl<'a> Parser<'a> {
1282112821
Some(GrantObjects::AllSequencesInSchema {
1282212822
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1282312823
})
12824+
} else if self.parse_keywords(&[Keyword::RESOURCE, Keyword::MONITOR]) {
12825+
Some(GrantObjects::ResourceMonitors(self.parse_comma_separated(
12826+
|p| p.parse_object_name_with_wildcards(false, true),
12827+
)?))
12828+
} else if self.parse_keywords(&[Keyword::COMPUTE, Keyword::POOL]) {
12829+
Some(GrantObjects::ComputePools(self.parse_comma_separated(
12830+
|p| p.parse_object_name_with_wildcards(false, true),
12831+
)?))
12832+
} else if self.parse_keywords(&[Keyword::FAILOVER, Keyword::GROUP]) {
12833+
Some(GrantObjects::FailoverGroup(self.parse_comma_separated(
12834+
|p| p.parse_object_name_with_wildcards(false, true),
12835+
)?))
12836+
} else if self.parse_keywords(&[Keyword::REPLICATION, Keyword::GROUP]) {
12837+
Some(GrantObjects::ReplicationGroup(self.parse_comma_separated(
12838+
|p| p.parse_object_name_with_wildcards(false, true),
12839+
)?))
12840+
} else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
12841+
Some(GrantObjects::ExternalVolumes(self.parse_comma_separated(
12842+
|p| p.parse_object_name_with_wildcards(false, true),
12843+
)?))
1282412844
} else {
1282512845
let object_type = self.parse_one_of_keywords(&[
1282612846
Keyword::SEQUENCE,
@@ -12834,6 +12854,8 @@ impl<'a> Parser<'a> {
1283412854
Keyword::VIEW,
1283512855
Keyword::WAREHOUSE,
1283612856
Keyword::INTEGRATION,
12857+
Keyword::USER,
12858+
Keyword::CONNECTION,
1283712859
]);
1283812860
let objects =
1283912861
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
@@ -12844,6 +12866,8 @@ impl<'a> Parser<'a> {
1284412866
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
1284512867
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
1284612868
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
12869+
Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
12870+
Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
1284712871
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
1284812872
_ => unreachable!(),
1284912873
}
@@ -12929,10 +12953,10 @@ impl<'a> Parser<'a> {
1292912953
let manage_type = self.parse_action_manage_type()?;
1293012954
Ok(Action::Manage { manage_type })
1293112955
} else if self.parse_keyword(Keyword::MODIFY) {
12932-
let modify_type = self.parse_action_modify_type()?;
12956+
let modify_type = self.parse_action_modify_type();
1293312957
Ok(Action::Modify { modify_type })
1293412958
} else if self.parse_keyword(Keyword::MONITOR) {
12935-
let monitor_type = self.parse_action_monitor_type()?;
12959+
let monitor_type = self.parse_action_monitor_type();
1293612960
Ok(Action::Monitor { monitor_type })
1293712961
} else if self.parse_keyword(Keyword::OPERATE) {
1293812962
Ok(Action::Operate)
@@ -13073,29 +13097,29 @@ impl<'a> Parser<'a> {
1307313097
}
1307413098
}
1307513099

13076-
fn parse_action_modify_type(&mut self) -> Result<ActionModifyType, ParserError> {
13100+
fn parse_action_modify_type(&mut self) -> Option<ActionModifyType> {
1307713101
if self.parse_keywords(&[Keyword::LOG, Keyword::LEVEL]) {
13078-
Ok(ActionModifyType::LogLevel)
13102+
Some(ActionModifyType::LogLevel)
1307913103
} else if self.parse_keywords(&[Keyword::TRACE, Keyword::LEVEL]) {
13080-
Ok(ActionModifyType::TraceLevel)
13104+
Some(ActionModifyType::TraceLevel)
1308113105
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::LOG, Keyword::LEVEL]) {
13082-
Ok(ActionModifyType::SessionLogLevel)
13106+
Some(ActionModifyType::SessionLogLevel)
1308313107
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::TRACE, Keyword::LEVEL]) {
13084-
Ok(ActionModifyType::SessionTraceLevel)
13108+
Some(ActionModifyType::SessionTraceLevel)
1308513109
} else {
13086-
self.expected("GRANT MODIFY type", self.peek_token())
13110+
None
1308713111
}
1308813112
}
1308913113

13090-
fn parse_action_monitor_type(&mut self) -> Result<ActionMonitorType, ParserError> {
13114+
fn parse_action_monitor_type(&mut self) -> Option<ActionMonitorType> {
1309113115
if self.parse_keyword(Keyword::EXECUTION) {
13092-
Ok(ActionMonitorType::Execution)
13116+
Some(ActionMonitorType::Execution)
1309313117
} else if self.parse_keyword(Keyword::SECURITY) {
13094-
Ok(ActionMonitorType::Security)
13118+
Some(ActionMonitorType::Security)
1309513119
} else if self.parse_keyword(Keyword::USAGE) {
13096-
Ok(ActionMonitorType::Usage)
13120+
Some(ActionMonitorType::Usage)
1309713121
} else {
13098-
self.expected("GRANT MONITOR type", self.peek_token())
13122+
None
1309913123
}
1310013124
}
1310113125

tests/sqlparser_snowflake.rs

Lines changed: 45 additions & 1 deletion
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");
@@ -3505,3 +3542,10 @@ fn test_alter_session() {
35053542
);
35063543
snowflake().one_statement_parses_to("ALTER SESSION UNSET a\nB", "ALTER SESSION UNSET a, B");
35073544
}
3545+
3546+
#[test]
3547+
fn test_xxx() {
3548+
snowflake()
3549+
.parse_sql_statements("grant monitor on warehouse ETL_ENV_SHARE to role \"abc\"")
3550+
.unwrap();
3551+
}

0 commit comments

Comments
 (0)