Skip to content

Commit 6afd194

Browse files
authored
Disambiguate CREATE ROLE ... USER and GROUP (#628)
1 parent 2b21da2 commit 6afd194

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

src/ast/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ pub enum Statement {
11171117
if_not_exists: bool,
11181118
},
11191119
/// CREATE ROLE
1120+
/// See [postgres](https://www.postgresql.org/docs/current/sql-createrole.html)
11201121
CreateRole {
11211122
names: Vec<ObjectName>,
11221123
if_not_exists: bool,
@@ -1132,7 +1133,9 @@ pub enum Statement {
11321133
connection_limit: Option<Expr>,
11331134
valid_until: Option<Expr>,
11341135
in_role: Vec<Ident>,
1136+
in_group: Vec<Ident>,
11351137
role: Vec<Ident>,
1138+
user: Vec<Ident>,
11361139
admin: Vec<Ident>,
11371140
// MSSQL
11381141
authorization_owner: Option<ObjectName>,
@@ -2005,7 +2008,9 @@ impl fmt::Display for Statement {
20052008
connection_limit,
20062009
valid_until,
20072010
in_role,
2011+
in_group,
20082012
role,
2013+
user,
20092014
admin,
20102015
authorization_owner,
20112016
} => {
@@ -2064,9 +2069,15 @@ impl fmt::Display for Statement {
20642069
if !in_role.is_empty() {
20652070
write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
20662071
}
2072+
if !in_group.is_empty() {
2073+
write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
2074+
}
20672075
if !role.is_empty() {
20682076
write!(f, " ROLE {}", display_comma_separated(role))?;
20692077
}
2078+
if !user.is_empty() {
2079+
write!(f, " USER {}", display_comma_separated(user))?;
2080+
}
20702081
if !admin.is_empty() {
20712082
write!(f, " ADMIN {}", display_comma_separated(admin))?;
20722083
}

src/parser.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,7 +2109,9 @@ impl<'a> Parser<'a> {
21092109
let mut connection_limit = None;
21102110
let mut valid_until = None;
21112111
let mut in_role = vec![];
2112-
let mut roles = vec![];
2112+
let mut in_group = vec![];
2113+
let mut role = vec![];
2114+
let mut user = vec![];
21132115
let mut admin = vec![];
21142116

21152117
while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) {
@@ -2209,22 +2211,37 @@ impl<'a> Parser<'a> {
22092211
}
22102212
}
22112213
Keyword::IN => {
2212-
if self.parse_keyword(Keyword::ROLE) || self.parse_keyword(Keyword::GROUP) {
2214+
if self.parse_keyword(Keyword::ROLE) {
22132215
if !in_role.is_empty() {
2214-
parser_err!("Found multiple IN ROLE or IN GROUP")
2216+
parser_err!("Found multiple IN ROLE")
22152217
} else {
22162218
in_role = self.parse_comma_separated(Parser::parse_identifier)?;
22172219
Ok(())
22182220
}
2221+
} else if self.parse_keyword(Keyword::GROUP) {
2222+
if !in_group.is_empty() {
2223+
parser_err!("Found multiple IN GROUP")
2224+
} else {
2225+
in_group = self.parse_comma_separated(Parser::parse_identifier)?;
2226+
Ok(())
2227+
}
22192228
} else {
22202229
self.expected("ROLE or GROUP after IN", self.peek_token())
22212230
}
22222231
}
2223-
Keyword::ROLE | Keyword::USER => {
2224-
if !roles.is_empty() {
2225-
parser_err!("Found multiple ROLE or USER")
2232+
Keyword::ROLE => {
2233+
if !role.is_empty() {
2234+
parser_err!("Found multiple ROLE")
2235+
} else {
2236+
role = self.parse_comma_separated(Parser::parse_identifier)?;
2237+
Ok(())
2238+
}
2239+
}
2240+
Keyword::USER => {
2241+
if !user.is_empty() {
2242+
parser_err!("Found multiple USER")
22262243
} else {
2227-
roles = self.parse_comma_separated(Parser::parse_identifier)?;
2244+
user = self.parse_comma_separated(Parser::parse_identifier)?;
22282245
Ok(())
22292246
}
22302247
}
@@ -2254,7 +2271,9 @@ impl<'a> Parser<'a> {
22542271
connection_limit,
22552272
valid_until,
22562273
in_role,
2257-
role: roles,
2274+
in_group,
2275+
role,
2276+
user,
22582277
admin,
22592278
authorization_owner,
22602279
})

tests/sqlparser_postgres.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,9 @@ fn parse_create_role() {
18071807
connection_limit,
18081808
valid_until,
18091809
in_role,
1810+
in_group,
18101811
role,
1812+
user,
18111813
admin,
18121814
authorization_owner,
18131815
}],
@@ -1833,13 +1835,29 @@ fn parse_create_role() {
18331835
Some(Expr::Value(Value::SingleQuotedString("2025-01-01".into())))
18341836
);
18351837
assert_eq_vec(&["role1", "role2"], in_role);
1838+
assert!(in_group.is_empty());
18361839
assert_eq_vec(&["role3"], role);
1840+
assert!(user.is_empty());
18371841
assert_eq_vec(&["role4", "role5"], admin);
18381842
assert_eq!(*authorization_owner, None);
18391843
}
18401844
err => panic!("Failed to parse CREATE ROLE test case: {:?}", err),
18411845
}
18421846

1847+
let sql = "CREATE ROLE abc WITH USER foo, bar ROLE baz ";
1848+
match pg().parse_sql_statements(sql).as_deref() {
1849+
Ok(
1850+
[Statement::CreateRole {
1851+
names, user, role, ..
1852+
}],
1853+
) => {
1854+
assert_eq_vec(&["abc"], names);
1855+
assert_eq_vec(&["foo", "bar"], user);
1856+
assert_eq_vec(&["baz"], role);
1857+
}
1858+
err => panic!("Failed to parse CREATE ROLE test case: {:?}", err),
1859+
}
1860+
18431861
let negatables = vec![
18441862
"BYPASSRLS",
18451863
"CREATEDB",

0 commit comments

Comments
 (0)