sqlparser/parser/
alter.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
13//! SQL Parser for ALTER
14
15#[cfg(not(feature = "std"))]
16use alloc::{string::ToString, vec};
17
18use super::{Parser, ParserError};
19use crate::{
20    ast::{
21        helpers::key_value_options::{KeyValueOptions, KeyValueOptionsDelimiter},
22        AlterConnectorOwner, AlterPolicyOperation, AlterRoleOperation, AlterUser,
23        AlterUserAddMfaMethodOtp, AlterUserAddRoleDelegation, AlterUserModifyMfaMethod,
24        AlterUserRemoveRoleDelegation, AlterUserSetPolicy, Expr, MfaMethodKind, Password,
25        ResetConfig, RoleOption, SetConfigValue, Statement, UserPolicyKind,
26    },
27    dialect::{MsSqlDialect, PostgreSqlDialect},
28    keywords::Keyword,
29    tokenizer::Token,
30};
31
32impl Parser<'_> {
33    pub fn parse_alter_role(&mut self) -> Result<Statement, ParserError> {
34        if dialect_of!(self is PostgreSqlDialect) {
35            return self.parse_pg_alter_role();
36        } else if dialect_of!(self is MsSqlDialect) {
37            return self.parse_mssql_alter_role();
38        }
39
40        Err(ParserError::ParserError(
41            "ALTER ROLE is only support for PostgreSqlDialect, MsSqlDialect".into(),
42        ))
43    }
44
45    /// Parse ALTER POLICY statement
46    /// ```sql
47    /// ALTER POLICY policy_name ON table_name [ RENAME TO new_name ]
48    /// or
49    /// ALTER POLICY policy_name ON table_name
50    /// [ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
51    /// [ USING ( using_expression ) ]
52    /// [ WITH CHECK ( check_expression ) ]
53    /// ```
54    ///
55    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterpolicy.html)
56    pub fn parse_alter_policy(&mut self) -> Result<Statement, ParserError> {
57        let name = self.parse_identifier()?;
58        self.expect_keyword_is(Keyword::ON)?;
59        let table_name = self.parse_object_name(false)?;
60
61        if self.parse_keyword(Keyword::RENAME) {
62            self.expect_keyword_is(Keyword::TO)?;
63            let new_name = self.parse_identifier()?;
64            Ok(Statement::AlterPolicy {
65                name,
66                table_name,
67                operation: AlterPolicyOperation::Rename { new_name },
68            })
69        } else {
70            let to = if self.parse_keyword(Keyword::TO) {
71                Some(self.parse_comma_separated(|p| p.parse_owner())?)
72            } else {
73                None
74            };
75
76            let using = if self.parse_keyword(Keyword::USING) {
77                self.expect_token(&Token::LParen)?;
78                let expr = self.parse_expr()?;
79                self.expect_token(&Token::RParen)?;
80                Some(expr)
81            } else {
82                None
83            };
84
85            let with_check = if self.parse_keywords(&[Keyword::WITH, Keyword::CHECK]) {
86                self.expect_token(&Token::LParen)?;
87                let expr = self.parse_expr()?;
88                self.expect_token(&Token::RParen)?;
89                Some(expr)
90            } else {
91                None
92            };
93            Ok(Statement::AlterPolicy {
94                name,
95                table_name,
96                operation: AlterPolicyOperation::Apply {
97                    to,
98                    using,
99                    with_check,
100                },
101            })
102        }
103    }
104
105    /// Parse an `ALTER CONNECTOR` statement
106    /// ```sql
107    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
108    ///
109    /// ALTER CONNECTOR connector_name SET URL new_url;
110    ///
111    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
112    /// ```
113    pub fn parse_alter_connector(&mut self) -> Result<Statement, ParserError> {
114        let name = self.parse_identifier()?;
115        self.expect_keyword_is(Keyword::SET)?;
116
117        let properties = match self.parse_options_with_keywords(&[Keyword::DCPROPERTIES])? {
118            properties if !properties.is_empty() => Some(properties),
119            _ => None,
120        };
121
122        let url = if self.parse_keyword(Keyword::URL) {
123            Some(self.parse_literal_string()?)
124        } else {
125            None
126        };
127
128        let owner = if self.parse_keywords(&[Keyword::OWNER, Keyword::USER]) {
129            let owner = self.parse_identifier()?;
130            Some(AlterConnectorOwner::User(owner))
131        } else if self.parse_keywords(&[Keyword::OWNER, Keyword::ROLE]) {
132            let owner = self.parse_identifier()?;
133            Some(AlterConnectorOwner::Role(owner))
134        } else {
135            None
136        };
137
138        Ok(Statement::AlterConnector {
139            name,
140            properties,
141            url,
142            owner,
143        })
144    }
145
146    /// Parse an `ALTER USER` statement
147    /// ```sql
148    /// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
149    /// ```
150    pub fn parse_alter_user(&mut self) -> Result<Statement, ParserError> {
151        let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
152        let name = self.parse_identifier()?;
153        let rename_to = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
154            Some(self.parse_identifier()?)
155        } else {
156            None
157        };
158        let reset_password = self.parse_keywords(&[Keyword::RESET, Keyword::PASSWORD]);
159        let abort_all_queries =
160            self.parse_keywords(&[Keyword::ABORT, Keyword::ALL, Keyword::QUERIES]);
161        let add_role_delegation = if self.parse_keywords(&[
162            Keyword::ADD,
163            Keyword::DELEGATED,
164            Keyword::AUTHORIZATION,
165            Keyword::OF,
166            Keyword::ROLE,
167        ]) {
168            let role = self.parse_identifier()?;
169            self.expect_keywords(&[Keyword::TO, Keyword::SECURITY, Keyword::INTEGRATION])?;
170            let integration = self.parse_identifier()?;
171            Some(AlterUserAddRoleDelegation { role, integration })
172        } else {
173            None
174        };
175        let remove_role_delegation = if self.parse_keywords(&[Keyword::REMOVE, Keyword::DELEGATED])
176        {
177            let role = if self.parse_keywords(&[Keyword::AUTHORIZATION, Keyword::OF, Keyword::ROLE])
178            {
179                Some(self.parse_identifier()?)
180            } else if self.parse_keyword(Keyword::AUTHORIZATIONS) {
181                None
182            } else {
183                return self.expected(
184                    "REMOVE DELEGATED AUTHORIZATION OF ROLE | REMOVE DELEGATED AUTHORIZATIONS",
185                    self.peek_token(),
186                );
187            };
188            self.expect_keywords(&[Keyword::FROM, Keyword::SECURITY, Keyword::INTEGRATION])?;
189            let integration = self.parse_identifier()?;
190            Some(AlterUserRemoveRoleDelegation { role, integration })
191        } else {
192            None
193        };
194        let enroll_mfa = self.parse_keywords(&[Keyword::ENROLL, Keyword::MFA]);
195        let set_default_mfa_method =
196            if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT_MFA_METHOD]) {
197                Some(self.parse_mfa_method()?)
198            } else {
199                None
200            };
201        let remove_mfa_method =
202            if self.parse_keywords(&[Keyword::REMOVE, Keyword::MFA, Keyword::METHOD]) {
203                Some(self.parse_mfa_method()?)
204            } else {
205                None
206            };
207        let modify_mfa_method =
208            if self.parse_keywords(&[Keyword::MODIFY, Keyword::MFA, Keyword::METHOD]) {
209                let method = self.parse_mfa_method()?;
210                self.expect_keywords(&[Keyword::SET, Keyword::COMMENT])?;
211                let comment = self.parse_literal_string()?;
212                Some(AlterUserModifyMfaMethod { method, comment })
213            } else {
214                None
215            };
216        let add_mfa_method_otp =
217            if self.parse_keywords(&[Keyword::ADD, Keyword::MFA, Keyword::METHOD, Keyword::OTP]) {
218                let count = if self.parse_keyword(Keyword::COUNT) {
219                    self.expect_token(&Token::Eq)?;
220                    Some(self.parse_value()?.into())
221                } else {
222                    None
223                };
224                Some(AlterUserAddMfaMethodOtp { count })
225            } else {
226                None
227            };
228        let set_policy =
229            if self.parse_keywords(&[Keyword::SET, Keyword::AUTHENTICATION, Keyword::POLICY]) {
230                Some(AlterUserSetPolicy {
231                    policy_kind: UserPolicyKind::Authentication,
232                    policy: self.parse_identifier()?,
233                })
234            } else if self.parse_keywords(&[Keyword::SET, Keyword::PASSWORD, Keyword::POLICY]) {
235                Some(AlterUserSetPolicy {
236                    policy_kind: UserPolicyKind::Password,
237                    policy: self.parse_identifier()?,
238                })
239            } else if self.parse_keywords(&[Keyword::SET, Keyword::SESSION, Keyword::POLICY]) {
240                Some(AlterUserSetPolicy {
241                    policy_kind: UserPolicyKind::Session,
242                    policy: self.parse_identifier()?,
243                })
244            } else {
245                None
246            };
247
248        let unset_policy =
249            if self.parse_keywords(&[Keyword::UNSET, Keyword::AUTHENTICATION, Keyword::POLICY]) {
250                Some(UserPolicyKind::Authentication)
251            } else if self.parse_keywords(&[Keyword::UNSET, Keyword::PASSWORD, Keyword::POLICY]) {
252                Some(UserPolicyKind::Password)
253            } else if self.parse_keywords(&[Keyword::UNSET, Keyword::SESSION, Keyword::POLICY]) {
254                Some(UserPolicyKind::Session)
255            } else {
256                None
257            };
258
259        let set_tag = if self.parse_keywords(&[Keyword::SET, Keyword::TAG]) {
260            self.parse_key_value_options(false, &[])?
261        } else {
262            KeyValueOptions {
263                delimiter: KeyValueOptionsDelimiter::Comma,
264                options: vec![],
265            }
266        };
267
268        let unset_tag = if self.parse_keywords(&[Keyword::UNSET, Keyword::TAG]) {
269            self.parse_comma_separated(Parser::parse_identifier)?
270                .iter()
271                .map(|i| i.to_string())
272                .collect()
273        } else {
274            vec![]
275        };
276
277        let set_props = if self.parse_keyword(Keyword::SET) {
278            self.parse_key_value_options(false, &[])?
279        } else {
280            KeyValueOptions {
281                delimiter: KeyValueOptionsDelimiter::Comma,
282                options: vec![],
283            }
284        };
285
286        let unset_props = if self.parse_keyword(Keyword::UNSET) {
287            self.parse_comma_separated(Parser::parse_identifier)?
288                .iter()
289                .map(|i| i.to_string())
290                .collect()
291        } else {
292            vec![]
293        };
294
295        Ok(Statement::AlterUser(AlterUser {
296            if_exists,
297            name,
298            rename_to,
299            reset_password,
300            abort_all_queries,
301            add_role_delegation,
302            remove_role_delegation,
303            enroll_mfa,
304            set_default_mfa_method,
305            remove_mfa_method,
306            modify_mfa_method,
307            add_mfa_method_otp,
308            set_policy,
309            unset_policy,
310            set_tag,
311            unset_tag,
312            set_props,
313            unset_props,
314        }))
315    }
316
317    fn parse_mfa_method(&mut self) -> Result<MfaMethodKind, ParserError> {
318        if self.parse_keyword(Keyword::PASSKEY) {
319            Ok(MfaMethodKind::PassKey)
320        } else if self.parse_keyword(Keyword::TOTP) {
321            Ok(MfaMethodKind::Totp)
322        } else if self.parse_keyword(Keyword::DUO) {
323            Ok(MfaMethodKind::Duo)
324        } else {
325            self.expected("PASSKEY, TOTP or DUO", self.peek_token())
326        }
327    }
328
329    fn parse_mssql_alter_role(&mut self) -> Result<Statement, ParserError> {
330        let role_name = self.parse_identifier()?;
331
332        let operation = if self.parse_keywords(&[Keyword::ADD, Keyword::MEMBER]) {
333            let member_name = self.parse_identifier()?;
334            AlterRoleOperation::AddMember { member_name }
335        } else if self.parse_keywords(&[Keyword::DROP, Keyword::MEMBER]) {
336            let member_name = self.parse_identifier()?;
337            AlterRoleOperation::DropMember { member_name }
338        } else if self.parse_keywords(&[Keyword::WITH, Keyword::NAME]) {
339            if self.consume_token(&Token::Eq) {
340                let role_name = self.parse_identifier()?;
341                AlterRoleOperation::RenameRole { role_name }
342            } else {
343                return self.expected("= after WITH NAME ", self.peek_token());
344            }
345        } else {
346            return self.expected("'ADD' or 'DROP' or 'WITH NAME'", self.peek_token());
347        };
348
349        Ok(Statement::AlterRole {
350            name: role_name,
351            operation,
352        })
353    }
354
355    fn parse_pg_alter_role(&mut self) -> Result<Statement, ParserError> {
356        let role_name = self.parse_identifier()?;
357
358        // [ IN DATABASE _`database_name`_ ]
359        let in_database = if self.parse_keywords(&[Keyword::IN, Keyword::DATABASE]) {
360            self.parse_object_name(false).ok()
361        } else {
362            None
363        };
364
365        let operation = if self.parse_keyword(Keyword::RENAME) {
366            if self.parse_keyword(Keyword::TO) {
367                let role_name = self.parse_identifier()?;
368                AlterRoleOperation::RenameRole { role_name }
369            } else {
370                return self.expected("TO after RENAME", self.peek_token());
371            }
372        // SET
373        } else if self.parse_keyword(Keyword::SET) {
374            let config_name = self.parse_object_name(false)?;
375            // FROM CURRENT
376            if self.parse_keywords(&[Keyword::FROM, Keyword::CURRENT]) {
377                AlterRoleOperation::Set {
378                    config_name,
379                    config_value: SetConfigValue::FromCurrent,
380                    in_database,
381                }
382            // { TO | = } { value | DEFAULT }
383            } else if self.consume_token(&Token::Eq) || self.parse_keyword(Keyword::TO) {
384                if self.parse_keyword(Keyword::DEFAULT) {
385                    AlterRoleOperation::Set {
386                        config_name,
387                        config_value: SetConfigValue::Default,
388                        in_database,
389                    }
390                } else if let Ok(expr) = self.parse_expr() {
391                    AlterRoleOperation::Set {
392                        config_name,
393                        config_value: SetConfigValue::Value(expr),
394                        in_database,
395                    }
396                } else {
397                    self.expected("config value", self.peek_token())?
398                }
399            } else {
400                self.expected("'TO' or '=' or 'FROM CURRENT'", self.peek_token())?
401            }
402        // RESET
403        } else if self.parse_keyword(Keyword::RESET) {
404            if self.parse_keyword(Keyword::ALL) {
405                AlterRoleOperation::Reset {
406                    config_name: ResetConfig::ALL,
407                    in_database,
408                }
409            } else {
410                let config_name = self.parse_object_name(false)?;
411                AlterRoleOperation::Reset {
412                    config_name: ResetConfig::ConfigName(config_name),
413                    in_database,
414                }
415            }
416        // option
417        } else {
418            // [ WITH ]
419            let _ = self.parse_keyword(Keyword::WITH);
420            // option
421            let mut options = vec![];
422            while let Some(opt) = self.maybe_parse(|parser| parser.parse_pg_role_option())? {
423                options.push(opt);
424            }
425            // check option
426            if options.is_empty() {
427                return self.expected("option", self.peek_token())?;
428            }
429
430            AlterRoleOperation::WithOptions { options }
431        };
432
433        Ok(Statement::AlterRole {
434            name: role_name,
435            operation,
436        })
437    }
438
439    fn parse_pg_role_option(&mut self) -> Result<RoleOption, ParserError> {
440        let option = match self.parse_one_of_keywords(&[
441            Keyword::BYPASSRLS,
442            Keyword::NOBYPASSRLS,
443            Keyword::CONNECTION,
444            Keyword::CREATEDB,
445            Keyword::NOCREATEDB,
446            Keyword::CREATEROLE,
447            Keyword::NOCREATEROLE,
448            Keyword::INHERIT,
449            Keyword::NOINHERIT,
450            Keyword::LOGIN,
451            Keyword::NOLOGIN,
452            Keyword::PASSWORD,
453            Keyword::REPLICATION,
454            Keyword::NOREPLICATION,
455            Keyword::SUPERUSER,
456            Keyword::NOSUPERUSER,
457            Keyword::VALID,
458        ]) {
459            Some(Keyword::BYPASSRLS) => RoleOption::BypassRLS(true),
460            Some(Keyword::NOBYPASSRLS) => RoleOption::BypassRLS(false),
461            Some(Keyword::CONNECTION) => {
462                self.expect_keyword_is(Keyword::LIMIT)?;
463                RoleOption::ConnectionLimit(Expr::Value(self.parse_number_value()?))
464            }
465            Some(Keyword::CREATEDB) => RoleOption::CreateDB(true),
466            Some(Keyword::NOCREATEDB) => RoleOption::CreateDB(false),
467            Some(Keyword::CREATEROLE) => RoleOption::CreateRole(true),
468            Some(Keyword::NOCREATEROLE) => RoleOption::CreateRole(false),
469            Some(Keyword::INHERIT) => RoleOption::Inherit(true),
470            Some(Keyword::NOINHERIT) => RoleOption::Inherit(false),
471            Some(Keyword::LOGIN) => RoleOption::Login(true),
472            Some(Keyword::NOLOGIN) => RoleOption::Login(false),
473            Some(Keyword::PASSWORD) => {
474                let password = if self.parse_keyword(Keyword::NULL) {
475                    Password::NullPassword
476                } else {
477                    Password::Password(Expr::Value(self.parse_value()?))
478                };
479                RoleOption::Password(password)
480            }
481            Some(Keyword::REPLICATION) => RoleOption::Replication(true),
482            Some(Keyword::NOREPLICATION) => RoleOption::Replication(false),
483            Some(Keyword::SUPERUSER) => RoleOption::SuperUser(true),
484            Some(Keyword::NOSUPERUSER) => RoleOption::SuperUser(false),
485            Some(Keyword::VALID) => {
486                self.expect_keyword_is(Keyword::UNTIL)?;
487                RoleOption::ValidUntil(Expr::Value(self.parse_value()?))
488            }
489            _ => self.expected("option", self.peek_token())?,
490        };
491
492        Ok(option)
493    }
494}