1use alloc::vec::Vec;
14
15use crate::{
16 Expression, Identifier, RoleOption, Span, Spanned,
17 create_role::parse_role_option,
18 expression::{PRIORITY_MAX, parse_expression_unreserved},
19 keywords::Keyword,
20 lexer::Token,
21 parser::{ParseError, Parser},
22};
23
24#[derive(Clone, Debug)]
26pub enum AlterRoleValue<'a> {
27 Value(Expression<'a>),
29 Default(Span),
31 FromCurrent(Span),
32}
33
34impl<'a> Spanned for AlterRoleValue<'a> {
35 fn span(&self) -> Span {
36 match self {
37 AlterRoleValue::Value(v) => v.span(),
38 AlterRoleValue::Default(v) => v.span(),
39 AlterRoleValue::FromCurrent(v) => v.span(),
40 }
41 }
42}
43
44#[derive(Clone, Debug)]
46pub enum AlterRoleAction<'a> {
47 RenameTo {
49 rename_to_span: Span,
50 new_name: Identifier<'a>,
51 },
52 ResetAll { reset_all_span: Span },
54 ResetInDatabase {
56 in_database_span: Span,
57 database_name: Identifier<'a>,
58 reset_span: Span,
59 parameter: Identifier<'a>,
60 },
61 SetInDatabase {
63 in_database_span: Span,
64 database_name: Identifier<'a>,
65 set_span: Span,
66 parameter: Identifier<'a>,
67 value: AlterRoleValue<'a>,
68 },
69 Set {
71 set_span: Span,
72 parameter: Identifier<'a>,
73 value: AlterRoleValue<'a>,
74 },
75 With {
77 with_span: Span,
78 options: Vec<RoleOption<'a>>,
79 },
80}
81
82impl<'a> Spanned for AlterRoleAction<'a> {
83 fn span(&self) -> Span {
84 match self {
85 AlterRoleAction::RenameTo {
86 rename_to_span,
87 new_name,
88 } => rename_to_span.join_span(new_name),
89 AlterRoleAction::ResetAll { reset_all_span } => reset_all_span.span(),
90 AlterRoleAction::ResetInDatabase {
91 in_database_span,
92 database_name,
93 reset_span,
94 parameter,
95 } => in_database_span
96 .join_span(database_name)
97 .join_span(reset_span)
98 .join_span(parameter),
99 AlterRoleAction::SetInDatabase {
100 in_database_span,
101 database_name,
102 set_span,
103 parameter,
104 value,
105 } => in_database_span
106 .join_span(database_name)
107 .join_span(set_span)
108 .join_span(parameter)
109 .join_span(value),
110 AlterRoleAction::Set {
111 set_span,
112 parameter,
113 value,
114 } => set_span.join_span(parameter).join_span(value),
115 AlterRoleAction::With { with_span, options } => with_span.join_span(options),
116 }
117 }
118}
119
120#[derive(Clone, Debug)]
122pub struct AlterRole<'a> {
123 pub alter_span: Span,
125 pub role_span: Span,
127 pub role_name: Identifier<'a>,
129 pub action: AlterRoleAction<'a>,
131}
132
133impl<'a> Spanned for AlterRole<'a> {
134 fn span(&self) -> Span {
135 self.alter_span
136 .join_span(&self.role_span)
137 .join_span(&self.role_name)
138 .join_span(&self.action)
139 }
140}
141
142pub(crate) fn parse_alter_role<'a>(
143 parser: &mut Parser<'a, '_>,
144 alter_span: Span,
145) -> Result<AlterRole<'a>, ParseError> {
146 let role_span = parser.consume_keyword(Keyword::ROLE)?;
147 parser.postgres_only(&role_span);
148
149 let role_name = parser.consume_plain_identifier_unreserved()?;
150
151 let action = match &parser.token {
152 Token::Ident(_, Keyword::RENAME) => {
153 let rename_to_span = parser.consume_keywords(&[Keyword::RENAME, Keyword::TO])?;
154 let new_name = parser.consume_plain_identifier_unreserved()?;
155 AlterRoleAction::RenameTo {
156 rename_to_span,
157 new_name,
158 }
159 }
160 Token::Ident(_, Keyword::IN) => {
161 let in_database_span = parser.consume_keywords(&[Keyword::IN, Keyword::DATABASE])?;
162 let database_name = parser.consume_plain_identifier_unreserved()?;
163
164 match &parser.token {
165 Token::Ident(_, Keyword::SET) => {
166 let set_span = parser.consume_keyword(Keyword::SET)?;
167 let parameter = parser.consume_plain_identifier_unreserved()?;
168
169 let value = if let Some(eq_span) = parser.skip_token(Token::Eq) {
170 if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
171 AlterRoleValue::Default(eq_span.join_span(&default_span))
172 } else {
173 AlterRoleValue::Value(parse_expression_unreserved(
174 parser,
175 PRIORITY_MAX,
176 )?)
177 }
178 } else if let Some(to_span) = parser.skip_keyword(Keyword::TO) {
179 if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
180 AlterRoleValue::Default(to_span.join_span(&default_span))
181 } else {
182 AlterRoleValue::Value(parse_expression_unreserved(
183 parser,
184 PRIORITY_MAX,
185 )?)
186 }
187 } else {
188 parser.expected_failure("'=' or 'TO'")?
189 };
190
191 AlterRoleAction::SetInDatabase {
192 in_database_span,
193 database_name,
194 set_span,
195 parameter,
196 value,
197 }
198 }
199 Token::Ident(_, Keyword::RESET) => {
200 let reset_span = parser.consume_keyword(Keyword::RESET)?;
201 let parameter = parser.consume_plain_identifier_unreserved()?;
202
203 AlterRoleAction::ResetInDatabase {
204 in_database_span,
205 database_name,
206 reset_span,
207 parameter,
208 }
209 }
210 _ => parser.expected_failure("'SET' or 'RESET'")?,
211 }
212 }
213 Token::Ident(_, Keyword::RESET) => {
214 let reset_all_span = parser.consume_keywords(&[Keyword::RESET, Keyword::ALL])?;
215 AlterRoleAction::ResetAll { reset_all_span }
216 }
217 Token::Ident(_, Keyword::SET) => {
218 let set_span = parser.consume_keyword(Keyword::SET)?;
219 let parameter = parser.consume_plain_identifier_unreserved()?;
220
221 let value = if matches!(parser.token, Token::Ident(_, Keyword::FROM)) {
222 let from_current_span =
223 parser.consume_keywords(&[Keyword::FROM, Keyword::CURRENT])?;
224 AlterRoleValue::FromCurrent(from_current_span)
225 } else if let Some(eq_span) = parser.skip_token(Token::Eq) {
226 if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
227 AlterRoleValue::Default(eq_span.join_span(&default_span))
228 } else {
229 AlterRoleValue::Value(parse_expression_unreserved(parser, PRIORITY_MAX)?)
230 }
231 } else if let Some(to_span) = parser.skip_keyword(Keyword::TO) {
232 if let Some(default_span) = parser.skip_keyword(Keyword::DEFAULT) {
233 AlterRoleValue::Default(to_span.join_span(&default_span))
234 } else {
235 AlterRoleValue::Value(parse_expression_unreserved(parser, PRIORITY_MAX)?)
236 }
237 } else {
238 parser.expected_failure("'=', 'TO', or 'FROM'")?
239 };
240
241 AlterRoleAction::Set {
242 set_span,
243 parameter,
244 value,
245 }
246 }
247 Token::Ident(_, Keyword::WITH) => {
248 let with_span = parser.consume_keyword(Keyword::WITH)?;
249 let mut options = Vec::new();
250 loop {
251 if let Some(opt) = parse_role_option(parser)? {
252 options.push(opt);
253 continue;
254 }
255 break;
256 }
257 AlterRoleAction::With { with_span, options }
258 }
259 _ => parser.expected_failure("ALTER ROLE action (RENAME, IN, RESET, SET, or WITH)")?,
260 };
261
262 Ok(AlterRole {
263 alter_span,
264 role_span,
265 role_name,
266 action,
267 })
268}