Skip to content

Commit 4d6ec1f

Browse files
committed
PostgreSQL: ALTER USER password option
1 parent 14703f0 commit 4d6ec1f

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

src/ast/mod.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10046,12 +10046,15 @@ impl fmt::Display for CreateUser {
1004610046

1004710047
/// Modifies the properties of a user
1004810048
///
10049-
/// Syntax:
10049+
/// [Snowflake Syntax]:
1005010050
/// ```sql
1005110051
/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
1005210052
/// ```
1005310053
///
10054-
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
10054+
/// [PostgreSQL Syntax]:(https://www.postgresql.org/docs/current/sql-alteruser.html)
10055+
/// ```sql
10056+
/// ALTER USER <role_specification> [ WITH ] option [ ... ]
10057+
/// ```
1005510058
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1005610059
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1005710060
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -10075,6 +10078,8 @@ pub struct AlterUser {
1007510078
pub unset_tag: Vec<String>,
1007610079
pub set_props: KeyValueOptions,
1007710080
pub unset_props: Vec<String>,
10081+
/// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
10082+
pub password: Option<AlterUserPassword>,
1007810083
}
1007910084

1008010085
/// ```sql
@@ -10251,6 +10256,34 @@ impl fmt::Display for AlterUser {
1025110256
if !self.unset_props.is_empty() {
1025210257
write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
1025310258
}
10259+
if let Some(password) = &self.password {
10260+
write!(f, " {}", password)?;
10261+
}
10262+
Ok(())
10263+
}
10264+
}
10265+
10266+
/// ```sql
10267+
/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
10268+
/// ```
10269+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10270+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10271+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10272+
pub struct AlterUserPassword {
10273+
pub encrypted: bool,
10274+
pub password: Option<String>,
10275+
}
10276+
10277+
impl Display for AlterUserPassword {
10278+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10279+
write!(f, "PASSWORD")?;
10280+
if self.encrypted {
10281+
write!(f, " ENCRYPTED")?;
10282+
}
10283+
match &self.password {
10284+
None => write!(f, " NULL")?,
10285+
Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
10286+
}
1025410287
Ok(())
1025510288
}
1025610289
}

src/parser/alter.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use crate::{
2121
helpers::key_value_options::{KeyValueOptions, KeyValueOptionsDelimiter},
2222
AlterConnectorOwner, AlterPolicyOperation, AlterRoleOperation, AlterUser,
2323
AlterUserAddMfaMethodOtp, AlterUserAddRoleDelegation, AlterUserModifyMfaMethod,
24-
AlterUserRemoveRoleDelegation, AlterUserSetPolicy, Expr, MfaMethodKind, Password,
25-
ResetConfig, RoleOption, SetConfigValue, Statement, UserPolicyKind,
24+
AlterUserPassword, AlterUserRemoveRoleDelegation, AlterUserSetPolicy, Expr, MfaMethodKind,
25+
Password, ResetConfig, RoleOption, SetConfigValue, Statement, UserPolicyKind,
2626
},
2727
dialect::{MsSqlDialect, PostgreSqlDialect},
2828
keywords::Keyword,
@@ -150,6 +150,7 @@ impl Parser<'_> {
150150
pub fn parse_alter_user(&mut self) -> Result<Statement, ParserError> {
151151
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
152152
let name = self.parse_identifier()?;
153+
let _ = self.parse_keyword(Keyword::WITH);
153154
let rename_to = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
154155
Some(self.parse_identifier()?)
155156
} else {
@@ -292,6 +293,24 @@ impl Parser<'_> {
292293
vec![]
293294
};
294295

296+
let encrypted = self.parse_keyword(Keyword::ENCRYPTED);
297+
let password = if self.parse_keyword(Keyword::PASSWORD) {
298+
if self.parse_keyword(Keyword::NULL) {
299+
Some(AlterUserPassword {
300+
encrypted,
301+
password: None,
302+
})
303+
} else {
304+
let password = self.parse_literal_string()?;
305+
Some(AlterUserPassword {
306+
encrypted,
307+
password: Some(password),
308+
})
309+
}
310+
} else {
311+
None
312+
};
313+
295314
Ok(Statement::AlterUser(AlterUser {
296315
if_exists,
297316
name,
@@ -311,6 +330,7 @@ impl Parser<'_> {
311330
unset_tag,
312331
set_props,
313332
unset_props,
333+
password,
314334
}))
315335
}
316336

tests/sqlparser_common.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17885,6 +17885,12 @@ fn test_parse_alter_user() {
1788517885
_ => unreachable!(),
1788617886
}
1788717887
verified_stmt("ALTER USER u1 SET DEFAULT_SECONDARY_ROLES=('ALL'), PASSWORD='secret', WORKLOAD_IDENTITY=(TYPE=AWS, ARN='arn:aws:iam::123456789:r1/')");
17888+
17889+
verified_stmt("ALTER USER u1 PASSWORD 'AAA'");
17890+
one_statement_parses_to(
17891+
"ALTER USER u1 WITH PASSWORD 'AAA'",
17892+
"ALTER USER u1 PASSWORD 'AAA'",
17893+
);
1788817894
}
1788917895

1789017896
#[test]

0 commit comments

Comments
 (0)