Disambiguate CREATE ROLE ... USER and GROUP (#628)

This commit is contained in:
Andrew Lamb 2022-09-27 13:56:29 -04:00 committed by GitHub
parent 2b21da2439
commit 6afd194e94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 8 deletions

View file

@ -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,
@ -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>,
@ -2005,7 +2008,9 @@ impl fmt::Display for Statement {
connection_limit,
valid_until,
in_role,
in_group,
role,
user,
admin,
authorization_owner,
} => {
@ -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))?;
}

View file

@ -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) {
@ -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 {
roles = self.parse_comma_separated(Parser::parse_identifier)?;
role = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
}
Keyword::USER => {
if !user.is_empty() {
parser_err!("Found multiple USER")
} else {
user = self.parse_comma_separated(Parser::parse_identifier)?;
Ok(())
}
}
@ -2254,7 +2271,9 @@ impl<'a> Parser<'a> {
connection_limit,
valid_until,
in_role,
role: roles,
in_group,
role,
user,
admin,
authorization_owner,
})

View file

@ -1807,7 +1807,9 @@ fn parse_create_role() {
connection_limit,
valid_until,
in_role,
in_group,
role,
user,
admin,
authorization_owner,
}],
@ -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",