Skip to content

Commit 31663d7

Browse files
Reject IF NOT EXISTS for PostgreSQL CREATE ROLE
1 parent 75a74ab commit 31663d7

5 files changed

Lines changed: 28 additions & 6 deletions

File tree

‎src/dialect/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,11 @@ pub trait Dialect: Debug + Any {
410410
false
411411
}
412412

413+
/// Returns true if `CREATE ROLE` accepts `IF NOT EXISTS`.
414+
fn supports_create_role_if_not_exists(&self) -> bool {
415+
true
416+
}
417+
413418
/// Returns true if the dialects supports `group sets, roll up, or cube` expressions.
414419
fn supports_group_by_expr(&self) -> bool {
415420
false

‎src/dialect/postgresql.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ impl Dialect for PostgreSqlDialect {
198198
true
199199
}
200200

201+
fn supports_create_role_if_not_exists(&self) -> bool {
202+
false
203+
}
204+
201205
fn prec_value(&self, prec: Precedence) -> u8 {
202206
match prec {
203207
Precedence::Period => PERIOD_PREC,

‎src/parser/mod.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7037,15 +7037,17 @@ impl<'a> Parser<'a> {
70377037
&mut self,
70387038
role_keyword: RoleKeyword,
70397039
) -> Result<CreateRole, ParserError> {
7040-
if matches!(role_keyword, RoleKeyword::Group)
7040+
let supports_if_not_exists = matches!(role_keyword, RoleKeyword::Role)
7041+
&& self.dialect.supports_create_role_if_not_exists();
7042+
if !supports_if_not_exists
70417043
&& self.peek_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])
70427044
{
70437045
return parser_err!(
7044-
"IF NOT EXISTS is not supported for CREATE GROUP",
7046+
format!("IF NOT EXISTS is not supported for CREATE {role_keyword}"),
70457047
self.peek_token_ref().span.start
70467048
);
70477049
}
7048-
let if_not_exists = matches!(role_keyword, RoleKeyword::Role)
7050+
let if_not_exists = supports_if_not_exists
70497051
&& self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
70507052
let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
70517053

‎tests/sqlparser_common.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10081,7 +10081,7 @@ fn parse_create_role() {
1008110081
}
1008210082

1008310083
let sql = "CREATE ROLE IF NOT EXISTS mysql_a, mysql_b";
10084-
match verified_stmt(sql) {
10084+
match all_dialects_where(|d| d.supports_create_role_if_not_exists()).verified_stmt(sql) {
1008510085
Statement::CreateRole(create_role) => {
1008610086
assert_eq_vec(&["mysql_a", "mysql_b"], &create_role.names);
1008710087
assert!(create_role.if_not_exists);

‎tests/sqlparser_postgres.rs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4453,11 +4453,11 @@ fn parse_operator_empty_parens_rejected() {
44534453

44544454
#[test]
44554455
fn parse_create_role() {
4456-
let sql = "CREATE ROLE IF NOT EXISTS mysql_a, mysql_b";
4456+
let sql = "CREATE ROLE mysql_a, mysql_b";
44574457
match pg().verified_stmt(sql) {
44584458
Statement::CreateRole(create_role) => {
44594459
assert_eq_vec(&["mysql_a", "mysql_b"], &create_role.names);
4460-
assert!(create_role.if_not_exists);
4460+
assert!(!create_role.if_not_exists);
44614461
}
44624462
_ => unreachable!(),
44634463
}
@@ -10295,3 +10295,14 @@ fn parse_user_group_statements_is_dialect_gated() {
1029510295
);
1029610296
}
1029710297
}
10298+
10299+
#[test]
10300+
fn parse_create_role_if_not_exists_rejected() {
10301+
assert_eq!(
10302+
pg().parse_sql_statements("CREATE ROLE IF NOT EXISTS r"),
10303+
Err(ParserError::ParserError(
10304+
"IF NOT EXISTS is not supported for CREATE ROLE".to_string()
10305+
))
10306+
);
10307+
pg().verified_stmt(r#"CREATE ROLE "IF""#);
10308+
}

0 commit comments

Comments
 (0)