Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d38c2d0

Browse files
committed
Add PostgreSQL CREATE USER and ALTER USER support
Currently, the library only supports `CREATE ROLE` and `ALTER ROLE` for PostgreSQL. `CREATE USER` and `ALTER USER` fail to parse with errors like `"Expected: an object type after CREATE, found: USER"` But in PostgreSQL reference: - `CREATE USER` is equivalent to `CREATE ROLE`, except that `LOGIN` is assumed by default - `ALTER USER` is an alias to `ALTER ROLE` - Both should support the same options as their ROLE counterparts This commit extends the existing `CreateRole` and `AlterRole` structures to distinct which keyword has been used: `USER` or `ROLE`. It allows these expressions to be parsed and displayed back.
1 parent 779dcf9 commit d38c2d0

File tree

6 files changed

+215
-5
lines changed

6 files changed

+215
-5
lines changed

‎src/ast/dcl.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ use sqlparser_derive::{Visit, VisitMut};
3131
use super::{display_comma_separated, Expr, Ident, Password};
3232
use crate::ast::{display_separated, ObjectName};
3333

34+
/// Represents whether ROLE or USER keyword was used in CREATE/ALTER statements.
35+
/// In PostgreSQL, CREATE USER and ALTER USER are equivalent to CREATE ROLE and ALTER ROLE,
36+
/// with CREATE USER having LOGIN enabled by default.
37+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
38+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
40+
pub enum RoleKeyword {
41+
Role,
42+
User,
43+
}
44+
45+
impl fmt::Display for RoleKeyword {
46+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47+
match self {
48+
RoleKeyword::Role => write!(f, "ROLE"),
49+
RoleKeyword::User => write!(f, "USER"),
50+
}
51+
}
52+
}
53+
3454
/// An option in `ROLE` statement.
3555
///
3656
/// <https://www.postgresql.org/docs/current/sql-createrole.html>

‎src/ast/mod.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub use self::data_type::{
5555
ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
5656
};
5757
pub use self::dcl::{
58-
AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
58+
AlterRoleOperation, ResetConfig, RoleKeyword,RoleOption, SecondaryRoles, SetConfigValue, Use,
5959
};
6060
pub use self::ddl::{
6161
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
@@ -3314,6 +3314,8 @@ pub enum Statement {
33143314
CreateRole {
33153315
names: Vec<ObjectName>,
33163316
if_not_exists: bool,
3317+
/// Whether ROLE or USER keyword was used
3318+
keyword: RoleKeyword,
33173319
// Postgres
33183320
login: Option<bool>,
33193321
inherit: Option<bool>,
@@ -3421,6 +3423,8 @@ pub enum Statement {
34213423
/// ```
34223424
AlterRole {
34233425
name: Ident,
3426+
/// Whether ROLE or USER keyword was used
3427+
keyword: RoleKeyword,
34243428
operation: AlterRoleOperation,
34253429
},
34263430
/// ```sql
@@ -5279,6 +5283,7 @@ impl fmt::Display for Statement {
52795283
Statement::CreateRole {
52805284
names,
52815285
if_not_exists,
5286+
keyword,
52825287
inherit,
52835288
login,
52845289
bypassrls,
@@ -5298,7 +5303,7 @@ impl fmt::Display for Statement {
52985303
} => {
52995304
write!(
53005305
f,
5301-
"CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
5306+
"CREATE {keyword} {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
53025307
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
53035308
names = display_separated(names, ", "),
53045309
superuser = match *superuser {
@@ -5337,6 +5342,7 @@ impl fmt::Display for Statement {
53375342
None => ""
53385343
}
53395344
)?;
5345+
53405346
if let Some(limit) = connection_limit {
53415347
write!(f, " CONNECTION LIMIT {limit}")?;
53425348
}
@@ -5506,8 +5512,12 @@ impl fmt::Display for Statement {
55065512
Statement::AlterType(AlterType { name, operation }) => {
55075513
write!(f, "ALTER TYPE {name} {operation}")
55085514
}
5509-
Statement::AlterRole { name, operation } => {
5510-
write!(f, "ALTER ROLE {name} {operation}")
5515+
Statement::AlterRole {
5516+
name,
5517+
keyword,
5518+
operation,
5519+
} => {
5520+
write!(f, "ALTER {keyword} {name} {operation}")
55115521
}
55125522
Statement::AlterPolicy {
55135523
name,

‎src/parser/alter.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use super::{Parser, ParserError};
1919
use crate::{
2020
ast::{
2121
AlterConnectorOwner, AlterPolicyOperation, AlterRoleOperation, Expr, Password, ResetConfig,
22-
RoleOption, SetConfigValue, Statement,
22+
RoleKeyword,RoleOption, SetConfigValue, Statement,
2323
},
2424
dialect::{MsSqlDialect, PostgreSqlDialect},
2525
keywords::Keyword,
@@ -39,6 +39,15 @@ impl Parser<'_> {
3939
))
4040
}
4141

42+
pub fn parse_alter_user(&mut self) -> Result<Statement, ParserError> {
43+
if dialect_of!(self is PostgreSqlDialect) {
44+
return self.parse_pg_alter_user();
45+
}
46+
Err(ParserError::ParserError(
47+
"ALTER USER is only supported for PostgreSqlDialect".into(),
48+
))
49+
}
50+
4251
/// Parse ALTER POLICY statement
4352
/// ```sql
4453
/// ALTER POLICY policy_name ON table_name [ RENAME TO new_name ]
@@ -162,11 +171,23 @@ impl Parser<'_> {
162171

163172
Ok(Statement::AlterRole {
164173
name: role_name,
174+
keyword: RoleKeyword::Role,
165175
operation,
166176
})
167177
}
168178

169179
fn parse_pg_alter_role(&mut self) -> Result<Statement, ParserError> {
180+
self.parse_pg_alter_role_or_user(RoleKeyword::Role)
181+
}
182+
183+
fn parse_pg_alter_user(&mut self) -> Result<Statement, ParserError> {
184+
self.parse_pg_alter_role_or_user(RoleKeyword::User)
185+
}
186+
187+
fn parse_pg_alter_role_or_user(
188+
&mut self,
189+
keyword: RoleKeyword,
190+
) -> Result<Statement, ParserError> {
170191
let role_name = self.parse_identifier()?;
171192

172193
// [ IN DATABASE _`database_name`_ ]
@@ -246,6 +267,7 @@ impl Parser<'_> {
246267

247268
Ok(Statement::AlterRole {
248269
name: role_name,
270+
keyword,
249271
operation,
250272
})
251273
}

‎src/parser/mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4788,6 +4788,10 @@ impl<'a> Parser<'a> {
47884788
}
47894789

47904790
fn parse_create_user(&mut self, or_replace: bool) -> Result<Statement, ParserError> {
4791+
if dialect_of!(self is PostgreSqlDialect) {
4792+
return self.parse_pg_create_user();
4793+
}
4794+
47914795
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
47924796
let name = self.parse_identifier()?;
47934797
let options = self.parse_key_value_options(false, &[Keyword::WITH, Keyword::TAG])?;
@@ -5995,6 +5999,17 @@ impl<'a> Parser<'a> {
59955999
}
59966000

59976001
pub fn parse_create_role(&mut self) -> Result<Statement, ParserError> {
6002+
self.parse_pg_create_role_or_user(RoleKeyword::Role)
6003+
}
6004+
6005+
pub fn parse_pg_create_user(&mut self) -> Result<Statement, ParserError> {
6006+
self.parse_pg_create_role_or_user(RoleKeyword::User)
6007+
}
6008+
6009+
fn parse_pg_create_role_or_user(
6010+
&mut self,
6011+
keyword: RoleKeyword,
6012+
) -> Result<Statement, ParserError> {
59986013
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
59996014
let names = self.parse_comma_separated(|p| p.parse_object_name(false))?;
60006015

@@ -6196,9 +6211,15 @@ impl<'a> Parser<'a> {
61966211
}?
61976212
}
61986213

6214+
// In PostgreSQL, CREATE USER defaults to LOGIN=true, CREATE ROLE defaults to LOGIN=false
6215+
if login.is_none() && keyword == RoleKeyword::User {
6216+
login = Some(true);
6217+
}
6218+
61996219
Ok(Statement::CreateRole {
62006220
names,
62016221
if_not_exists,
6222+
keyword,
62026223
login,
62036224
inherit,
62046225
bypassrls,
@@ -9263,6 +9284,7 @@ impl<'a> Parser<'a> {
92639284
Keyword::TABLE,
92649285
Keyword::INDEX,
92659286
Keyword::ROLE,
9287+
Keyword::USER,
92669288
Keyword::POLICY,
92679289
Keyword::CONNECTOR,
92689290
Keyword::ICEBERG,
@@ -9300,6 +9322,7 @@ impl<'a> Parser<'a> {
93009322
})
93019323
}
93029324
Keyword::ROLE => self.parse_alter_role(),
9325+
Keyword::USER => self.parse_alter_user(),
93039326
Keyword::POLICY => self.parse_alter_policy(),
93049327
Keyword::CONNECTOR => self.parse_alter_connector(),
93059328
// unreachable because expect_one_of_keywords used above

‎tests/sqlparser_mssql.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ fn parse_alter_role() {
802802
quote_style: None,
803803
span: Span::empty(),
804804
},
805+
keyword: RoleKeyword::Role,
805806
operation: AlterRoleOperation::RenameRole {
806807
role_name: Ident {
807808
value: "new_name".into(),
@@ -821,6 +822,7 @@ fn parse_alter_role() {
821822
quote_style: None,
822823
span: Span::empty(),
823824
},
825+
keyword: RoleKeyword::Role,
824826
operation: AlterRoleOperation::AddMember {
825827
member_name: Ident {
826828
value: "new_member".into(),
@@ -840,6 +842,7 @@ fn parse_alter_role() {
840842
quote_style: None,
841843
span: Span::empty(),
842844
},
845+
keyword: RoleKeyword::Role,
843846
operation: AlterRoleOperation::DropMember {
844847
member_name: Ident {
845848
value: "old_member".into(),

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /