Skip to content

Commit a488e97

Browse files
yoavcloudayman-sigma
authored andcommitted
Add support for granting privileges to procedures and functions in Snowflake (apache#1930)
1 parent 3bc8dc3 commit a488e97

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

src/ast/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7052,6 +7052,25 @@ pub enum GrantObjects {
70527052
ReplicationGroup(Vec<ObjectName>),
70537053
/// Grant privileges on external volumes
70547054
ExternalVolumes(Vec<ObjectName>),
7055+
/// Grant privileges on a procedure. In dialects that
7056+
/// support overloading, the argument types must be specified.
7057+
///
7058+
/// For example:
7059+
/// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7060+
Procedure {
7061+
name: ObjectName,
7062+
arg_types: Vec<DataType>,
7063+
},
7064+
7065+
/// Grant privileges on a function. In dialects that
7066+
/// support overloading, the argument types must be specified.
7067+
///
7068+
/// For example:
7069+
/// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7070+
Function {
7071+
name: ObjectName,
7072+
arg_types: Vec<DataType>,
7073+
},
70557074
}
70567075

70577076
impl fmt::Display for GrantObjects {
@@ -7176,6 +7195,20 @@ impl fmt::Display for GrantObjects {
71767195
GrantObjects::ExternalVolumes(objects) => {
71777196
write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
71787197
}
7198+
GrantObjects::Procedure { name, arg_types } => {
7199+
write!(f, "PROCEDURE {name}")?;
7200+
if !arg_types.is_empty() {
7201+
write!(f, "({})", display_comma_separated(arg_types))?;
7202+
}
7203+
Ok(())
7204+
}
7205+
GrantObjects::Function { name, arg_types } => {
7206+
write!(f, "FUNCTION {name}")?;
7207+
if !arg_types.is_empty() {
7208+
write!(f, "({})", display_comma_separated(arg_types))?;
7209+
}
7210+
Ok(())
7211+
}
71797212
}
71807213
}
71817214
}

src/parser/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14093,6 +14093,8 @@ impl<'a> Parser<'a> {
1409314093
Keyword::INTEGRATION,
1409414094
Keyword::USER,
1409514095
Keyword::CONNECTION,
14096+
Keyword::PROCEDURE,
14097+
Keyword::FUNCTION,
1409614098
]);
1409714099
let objects =
1409814100
self.parse_comma_separated(|p| p.parse_object_name_inner(false, true));
@@ -14105,6 +14107,13 @@ impl<'a> Parser<'a> {
1410514107
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
1410614108
Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
1410714109
Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
14110+
kw @ (Some(Keyword::PROCEDURE) | Some(Keyword::FUNCTION)) => {
14111+
if let Some(name) = objects?.first() {
14112+
self.parse_grant_procedure_or_function(name, &kw)?
14113+
} else {
14114+
self.expected("procedure or function name", self.peek_token())?
14115+
}
14116+
}
1410814117
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
1410914118
_ => unreachable!(),
1411014119
}
@@ -14116,6 +14125,31 @@ impl<'a> Parser<'a> {
1411614125
Ok((privileges, objects))
1411714126
}
1411814127

14128+
fn parse_grant_procedure_or_function(
14129+
&mut self,
14130+
name: &ObjectName,
14131+
kw: &Option<Keyword>,
14132+
) -> Result<Option<GrantObjects>, ParserError> {
14133+
let arg_types = if self.consume_token(&Token::LParen) {
14134+
let list = self.parse_comma_separated0(Self::parse_data_type, Token::RParen)?;
14135+
self.expect_token(&Token::RParen)?;
14136+
list
14137+
} else {
14138+
vec![]
14139+
};
14140+
match kw {
14141+
Some(Keyword::PROCEDURE) => Ok(Some(GrantObjects::Procedure {
14142+
name: name.clone(),
14143+
arg_types,
14144+
})),
14145+
Some(Keyword::FUNCTION) => Ok(Some(GrantObjects::Function {
14146+
name: name.clone(),
14147+
arg_types,
14148+
})),
14149+
_ => self.expected("procedure or function keywords", self.peek_token())?,
14150+
}
14151+
}
14152+
1411914153
pub fn parse_grant_permission(&mut self) -> Result<Action, ParserError> {
1412014154
fn parse_columns(parser: &mut Parser) -> Result<Option<Vec<Ident>>, ParserError> {
1412114155
let columns = parser.parse_parenthesized_column_list(Optional, false)?;

tests/sqlparser_common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9461,6 +9461,8 @@ fn parse_grant() {
94619461
verified_stmt("GRANT SELECT ON FUTURE VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
94629462
verified_stmt("GRANT SELECT ON FUTURE MATERIALIZED VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
94639463
verified_stmt("GRANT SELECT ON FUTURE SEQUENCES IN SCHEMA db1.sc1 TO ROLE role1");
9464+
verified_stmt("GRANT USAGE ON PROCEDURE db1.sc1.foo(INT) TO ROLE role1");
9465+
verified_stmt("GRANT USAGE ON FUNCTION db1.sc1.foo(INT) TO ROLE role1");
94649466
}
94659467

94669468
#[test]

0 commit comments

Comments
 (0)