Skip to main content

qusql_parse/
alter_role.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use 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/// Parameters value for ALTER ROLE SET/RESET
25#[derive(Clone, Debug)]
26pub enum AlterRoleValue<'a> {
27    /// = value or TO value
28    Value(Expression<'a>),
29    /// TO DEFAULT or FROM CURRENT
30    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/// Actions that can be performed in ALTER ROLE
45#[derive(Clone, Debug)]
46pub enum AlterRoleAction<'a> {
47    /// RENAME TO new_name
48    RenameTo {
49        rename_to_span: Span,
50        new_name: Identifier<'a>,
51    },
52    /// RESET ALL
53    ResetAll { reset_all_span: Span },
54    /// IN DATABASE database_name RESET parameter
55    ResetInDatabase {
56        in_database_span: Span,
57        database_name: Identifier<'a>,
58        reset_span: Span,
59        parameter: Identifier<'a>,
60    },
61    /// IN DATABASE database_name SET parameter = value
62    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 parameter = value
70    Set {
71        set_span: Span,
72        parameter: Identifier<'a>,
73        value: AlterRoleValue<'a>,
74    },
75    /// WITH options
76    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/// ALTER ROLE statement (PostgreSQL)
121#[derive(Clone, Debug)]
122pub struct AlterRole<'a> {
123    /// Span of "ALTER"
124    pub alter_span: Span,
125    /// Span of "ROLE"
126    pub role_span: Span,
127    /// Name of the role to alter
128    pub role_name: Identifier<'a>,
129    /// Action to perform
130    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}