Skip to main content

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