mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-03 22:08:16 +00:00
Disambiguate CREATE ROLE ... USER and GROUP (#628)
This commit is contained in:
parent
2b21da2439
commit
6afd194e94
3 changed files with 56 additions and 8 deletions
|
@ -1117,6 +1117,7 @@ pub enum Statement {
|
||||||
if_not_exists: bool,
|
if_not_exists: bool,
|
||||||
},
|
},
|
||||||
/// CREATE ROLE
|
/// CREATE ROLE
|
||||||
|
/// See [postgres](https://www.postgresql.org/docs/current/sql-createrole.html)
|
||||||
CreateRole {
|
CreateRole {
|
||||||
names: Vec<ObjectName>,
|
names: Vec<ObjectName>,
|
||||||
if_not_exists: bool,
|
if_not_exists: bool,
|
||||||
|
@ -1132,7 +1133,9 @@ pub enum Statement {
|
||||||
connection_limit: Option<Expr>,
|
connection_limit: Option<Expr>,
|
||||||
valid_until: Option<Expr>,
|
valid_until: Option<Expr>,
|
||||||
in_role: Vec<Ident>,
|
in_role: Vec<Ident>,
|
||||||
|
in_group: Vec<Ident>,
|
||||||
role: Vec<Ident>,
|
role: Vec<Ident>,
|
||||||
|
user: Vec<Ident>,
|
||||||
admin: Vec<Ident>,
|
admin: Vec<Ident>,
|
||||||
// MSSQL
|
// MSSQL
|
||||||
authorization_owner: Option<ObjectName>,
|
authorization_owner: Option<ObjectName>,
|
||||||
|
@ -2005,7 +2008,9 @@ impl fmt::Display for Statement {
|
||||||
connection_limit,
|
connection_limit,
|
||||||
valid_until,
|
valid_until,
|
||||||
in_role,
|
in_role,
|
||||||
|
in_group,
|
||||||
role,
|
role,
|
||||||
|
user,
|
||||||
admin,
|
admin,
|
||||||
authorization_owner,
|
authorization_owner,
|
||||||
} => {
|
} => {
|
||||||
|
@ -2064,9 +2069,15 @@ impl fmt::Display for Statement {
|
||||||
if !in_role.is_empty() {
|
if !in_role.is_empty() {
|
||||||
write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
|
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() {
|
if !role.is_empty() {
|
||||||
write!(f, " ROLE {}", display_comma_separated(role))?;
|
write!(f, " ROLE {}", display_comma_separated(role))?;
|
||||||
}
|
}
|
||||||
|
if !user.is_empty() {
|
||||||
|
write!(f, " USER {}", display_comma_separated(user))?;
|
||||||
|
}
|
||||||
if !admin.is_empty() {
|
if !admin.is_empty() {
|
||||||
write!(f, " ADMIN {}", display_comma_separated(admin))?;
|
write!(f, " ADMIN {}", display_comma_separated(admin))?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2109,7 +2109,9 @@ impl<'a> Parser<'a> {
|
||||||
let mut connection_limit = None;
|
let mut connection_limit = None;
|
||||||
let mut valid_until = None;
|
let mut valid_until = None;
|
||||||
let mut in_role = vec![];
|
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![];
|
let mut admin = vec![];
|
||||||
|
|
||||||
while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) {
|
while let Some(keyword) = self.parse_one_of_keywords(&optional_keywords) {
|
||||||
|
@ -2209,22 +2211,37 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keyword::IN => {
|
Keyword::IN => {
|
||||||
if self.parse_keyword(Keyword::ROLE) || self.parse_keyword(Keyword::GROUP) {
|
if self.parse_keyword(Keyword::ROLE) {
|
||||||
if !in_role.is_empty() {
|
if !in_role.is_empty() {
|
||||||
parser_err!("Found multiple IN ROLE or IN GROUP")
|
parser_err!("Found multiple IN ROLE")
|
||||||
} else {
|
} else {
|
||||||
in_role = self.parse_comma_separated(Parser::parse_identifier)?;
|
in_role = self.parse_comma_separated(Parser::parse_identifier)?;
|
||||||
Ok(())
|
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 {
|
} else {
|
||||||
self.expected("ROLE or GROUP after IN", self.peek_token())
|
self.expected("ROLE or GROUP after IN", self.peek_token())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keyword::ROLE | Keyword::USER => {
|
Keyword::ROLE => {
|
||||||
if !roles.is_empty() {
|
if !role.is_empty() {
|
||||||
parser_err!("Found multiple ROLE or USER")
|
parser_err!("Found multiple ROLE")
|
||||||
} else {
|
} 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2254,7 +2271,9 @@ impl<'a> Parser<'a> {
|
||||||
connection_limit,
|
connection_limit,
|
||||||
valid_until,
|
valid_until,
|
||||||
in_role,
|
in_role,
|
||||||
role: roles,
|
in_group,
|
||||||
|
role,
|
||||||
|
user,
|
||||||
admin,
|
admin,
|
||||||
authorization_owner,
|
authorization_owner,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1807,7 +1807,9 @@ fn parse_create_role() {
|
||||||
connection_limit,
|
connection_limit,
|
||||||
valid_until,
|
valid_until,
|
||||||
in_role,
|
in_role,
|
||||||
|
in_group,
|
||||||
role,
|
role,
|
||||||
|
user,
|
||||||
admin,
|
admin,
|
||||||
authorization_owner,
|
authorization_owner,
|
||||||
}],
|
}],
|
||||||
|
@ -1833,13 +1835,29 @@ fn parse_create_role() {
|
||||||
Some(Expr::Value(Value::SingleQuotedString("2025-01-01".into())))
|
Some(Expr::Value(Value::SingleQuotedString("2025-01-01".into())))
|
||||||
);
|
);
|
||||||
assert_eq_vec(&["role1", "role2"], in_role);
|
assert_eq_vec(&["role1", "role2"], in_role);
|
||||||
|
assert!(in_group.is_empty());
|
||||||
assert_eq_vec(&["role3"], role);
|
assert_eq_vec(&["role3"], role);
|
||||||
|
assert!(user.is_empty());
|
||||||
assert_eq_vec(&["role4", "role5"], admin);
|
assert_eq_vec(&["role4", "role5"], admin);
|
||||||
assert_eq!(*authorization_owner, None);
|
assert_eq!(*authorization_owner, None);
|
||||||
}
|
}
|
||||||
err => panic!("Failed to parse CREATE ROLE test case: {:?}", err),
|
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![
|
let negatables = vec![
|
||||||
"BYPASSRLS",
|
"BYPASSRLS",
|
||||||
"CREATEDB",
|
"CREATEDB",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue