Skip to content

Commit

Permalink
Disambiguate CREATE ROLE ... USER and GROUP (#628)
Browse files Browse the repository at this point in the history
  • Loading branch information
alamb committed Sep 27, 2022
1 parent 2b21da2 commit 6afd194
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 8 deletions.
11 changes: 11 additions & 0 deletions src/ast/mod.rs
Expand Up @@ -1117,6 +1117,7 @@ pub enum Statement {
if_not_exists: bool,
},
/// CREATE ROLE
/// See [postgres](https://www.postgresql.org/docs/current/sql-createrole.html)
CreateRole {
names: Vec<ObjectName>,
if_not_exists: bool,
Expand All @@ -1132,7 +1133,9 @@ pub enum Statement {
connection_limit: Option<Expr>,
valid_until: Option<Expr>,
in_role: Vec<Ident>,
in_group: Vec<Ident>,
role: Vec<Ident>,
user: Vec<Ident>,
admin: Vec<Ident>,
// MSSQL
authorization_owner: Option<ObjectName>,
Expand Down Expand Up @@ -2005,7 +2008,9 @@ impl fmt::Display for Statement {
connection_limit,
valid_until,
in_role,
in_group,
role,
user,
admin,
authorization_owner,
} => {
Expand Down Expand Up @@ -2064,9 +2069,15 @@ impl fmt::Display for Statement {
if !in_role.is_empty() {
write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
}
if !in_group.is_empty() {
write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
}
if !role.is_empty() {
write!(f, " ROLE {}", display_comma_separated(role))?;
}
if !user.is_empty() {
write!(f, " USER {}", display_comma_separated(user))?;
}
if !admin.is_empty() {
write!(f, " ADMIN {}", display_comma_separated(admin))?;
}
Expand Down
35 changes: 27 additions & 8 deletions src/parser.rs
Expand Up @@ -2109,7 +2109,9 @@ impl<'a> Parser<'a> {
let mut connection_limit = None;
let mut valid_until = None;
let mut in_role = vec![];
let mut roles = vec![];
let mut in_group = vec![];
let mut role = vec![];
let mut user = vec![];
let mut admin = vec![];

while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) {
Expand Down Expand Up @@ -2209,22 +2211,37 @@ impl<'a> Parser<'a> {
}
}
Keyword::IN => {
if self.parse_keyword(Keyword::ROLE) || self.parse_keyword(Keyword::GROUP) {
if self.parse_keyword(Keyword::ROLE) {
if !in_role.is_empty() {
parser_err!("Found multiple IN ROLE or IN GROUP")
parser_err!("Found multiple IN ROLE")
} else {
in_role = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
} else if self.parse_keyword(Keyword::GROUP) {
if !in_group.is_empty() {
parser_err!("Found multiple IN GROUP")
} else {
in_group = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
} else {
self.expected("ROLE or GROUP after IN", self.peek_token())
}
}
Keyword::ROLE | Keyword::USER => {
if !roles.is_empty() {
parser_err!("Found multiple ROLE or USER")
Keyword::ROLE => {
if !role.is_empty() {
parser_err!("Found multiple ROLE")
} else {
role = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
}
Keyword::USER => {
if !user.is_empty() {
parser_err!("Found multiple USER")
} else {
roles = self.parse_comma_separated(Parser::parse_identifier)?;
user = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
}
Expand Down Expand Up @@ -2254,7 +2271,9 @@ impl<'a> Parser<'a> {
connection_limit,
valid_until,
in_role,
role: roles,
in_group,
role,
user,
admin,
authorization_owner,
})
Expand Down
18 changes: 18 additions & 0 deletions tests/sqlparser_postgres.rs
Expand Up @@ -1807,7 +1807,9 @@ fn parse_create_role() {
connection_limit,
valid_until,
in_role,
in_group,
role,
user,
admin,
authorization_owner,
}],
Expand All @@ -1833,13 +1835,29 @@ fn parse_create_role() {
Some(Expr::Value(Value::SingleQuotedString("2025-01-01".into())))
);
assert_eq_vec(&["role1", "role2"], in_role);
assert!(in_group.is_empty());
assert_eq_vec(&["role3"], role);
assert!(user.is_empty());
assert_eq_vec(&["role4", "role5"], admin);
assert_eq!(*authorization_owner, None);
}
err => panic!("Failed to parse CREATE ROLE test case: {:?}", err),
}

let sql = "CREATE ROLE abc WITH USER foo, bar ROLE baz ";
match pg().parse_sql_statements(sql).as_deref() {
Ok(
[Statement::CreateRole {
names, user, role, ..
}],
) => {
assert_eq_vec(&["abc"], names);
assert_eq_vec(&["foo", "bar"], user);
assert_eq_vec(&["baz"], role);
}
err => panic!("Failed to parse CREATE ROLE test case: {:?}", err),
}

let negatables = vec![
"BYPASSRLS",
"CREATEDB",
Expand Down

0 comments on commit 6afd194

Please sign in to comment.