Skip to content

Commit 7a6ada5

Browse files
committed
Add support for granting privileges to procedures and functions in Snowflake
1 parent 1a33abd commit 7a6ada5

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
@@ -6974,6 +6974,25 @@ pub enum GrantObjects {
69746974
ReplicationGroup(Vec<ObjectName>),
69756975
/// Grant privileges on external volumes
69766976
ExternalVolumes(Vec<ObjectName>),
6977+
/// Grant privileges on a procedure. In dialects that
6978+
/// support overloading, the argument types must be specified.
6979+
///
6980+
/// For example:
6981+
/// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
6982+
Procedure {
6983+
name: ObjectName,
6984+
arg_types: Vec<DataType>,
6985+
},
6986+
6987+
/// Grant privileges on a function. In dialects that
6988+
/// support overloading, the argument types must be specified.
6989+
///
6990+
/// For example:
6991+
/// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
6992+
Function {
6993+
name: ObjectName,
6994+
arg_types: Vec<DataType>,
6995+
},
69776996
}
69786997

69796998
impl fmt::Display for GrantObjects {
@@ -7098,6 +7117,20 @@ impl fmt::Display for GrantObjects {
70987117
GrantObjects::ExternalVolumes(objects) => {
70997118
write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
71007119
}
7120+
GrantObjects::Procedure { name, arg_types } => {
7121+
write!(f, "PROCEDURE {name}")?;
7122+
if !arg_types.is_empty() {
7123+
write!(f, "({})", display_comma_separated(arg_types))?;
7124+
}
7125+
Ok(())
7126+
}
7127+
GrantObjects::Function { name, arg_types } => {
7128+
write!(f, "FUNCTION {name}")?;
7129+
if !arg_types.is_empty() {
7130+
write!(f, "({})", display_comma_separated(arg_types))?;
7131+
}
7132+
Ok(())
7133+
}
71017134
}
71027135
}
71037136
}

src/parser/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14029,6 +14029,8 @@ impl<'a> Parser<'a> {
1402914029
Keyword::INTEGRATION,
1403014030
Keyword::USER,
1403114031
Keyword::CONNECTION,
14032+
Keyword::PROCEDURE,
14033+
Keyword::FUNCTION,
1403214034
]);
1403314035
let objects =
1403414036
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
@@ -14041,6 +14043,13 @@ impl<'a> Parser<'a> {
1404114043
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
1404214044
Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
1404314045
Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
14046+
kw @ (Some(Keyword::PROCEDURE) | Some(Keyword::FUNCTION)) => {
14047+
if let Some(name) = objects?.first() {
14048+
self.parse_grant_procedure_or_function(name, &kw)?
14049+
} else {
14050+
self.expected("procedure or function name", self.peek_token())?
14051+
}
14052+
}
1404414053
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
1404514054
_ => unreachable!(),
1404614055
}
@@ -14052,6 +14061,31 @@ impl<'a> Parser<'a> {
1405214061
Ok((privileges, objects))
1405314062
}
1405414063

14064+
fn parse_grant_procedure_or_function(
14065+
&mut self,
14066+
name: &ObjectName,
14067+
kw: &Option<Keyword>,
14068+
) -> Result<Option<GrantObjects>, ParserError> {
14069+
let arg_types = if self.consume_token(&Token::LParen) {
14070+
let list = self.parse_comma_separated0(Self::parse_data_type, Token::RParen)?;
14071+
self.expect_token(&Token::RParen)?;
14072+
list
14073+
} else {
14074+
vec![]
14075+
};
14076+
match kw {
14077+
Some(Keyword::PROCEDURE) => Ok(Some(GrantObjects::Procedure {
14078+
name: name.clone(),
14079+
arg_types,
14080+
})),
14081+
Some(Keyword::FUNCTION) => Ok(Some(GrantObjects::Function {
14082+
name: name.clone(),
14083+
arg_types,
14084+
})),
14085+
_ => self.expected("procedure or function keywords", self.peek_token())?,
14086+
}
14087+
}
14088+
1405514089
pub fn parse_grant_permission(&mut self) -> Result<Action, ParserError> {
1405614090
fn parse_columns(parser: &mut Parser) -> Result<Option<Vec<Ident>>, ParserError> {
1405714091
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
@@ -9454,6 +9454,8 @@ fn parse_grant() {
94549454
verified_stmt("GRANT SELECT ON FUTURE VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
94559455
verified_stmt("GRANT SELECT ON FUTURE MATERIALIZED VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
94569456
verified_stmt("GRANT SELECT ON FUTURE SEQUENCES IN SCHEMA db1.sc1 TO ROLE role1");
9457+
verified_stmt("GRANT USAGE ON PROCEDURE db1.sc1.foo(INT) TO ROLE role1");
9458+
verified_stmt("GRANT USAGE ON FUNCTION db1.sc1.foo(INT) TO ROLE role1");
94579459
}
94589460

94599461
#[test]

0 commit comments

Comments
 (0)