sqlparser/ast/
dcl.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! AST types specific to GRANT/REVOKE/ROLE variants of [`Statement`](crate::ast::Statement)
19//! (commonly referred to as Data Control Language, or DCL)
20
21#[cfg(not(feature = "std"))]
22use alloc::vec::Vec;
23use core::fmt;
24
25#[cfg(feature = "serde")]
26use serde::{Deserialize, Serialize};
27
28#[cfg(feature = "visitor")]
29use sqlparser_derive::{Visit, VisitMut};
30
31use super::{display_comma_separated, Expr, Ident, Password};
32use crate::ast::{display_separated, ObjectName};
33
34/// An option in `ROLE` statement.
35///
36/// <https://www.postgresql.org/docs/current/sql-createrole.html>
37#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
38#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
40pub enum RoleOption {
41    BypassRLS(bool),
42    ConnectionLimit(Expr),
43    CreateDB(bool),
44    CreateRole(bool),
45    Inherit(bool),
46    Login(bool),
47    Password(Password),
48    Replication(bool),
49    SuperUser(bool),
50    ValidUntil(Expr),
51}
52
53impl fmt::Display for RoleOption {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        match self {
56            RoleOption::BypassRLS(value) => {
57                write!(f, "{}", if *value { "BYPASSRLS" } else { "NOBYPASSRLS" })
58            }
59            RoleOption::ConnectionLimit(expr) => {
60                write!(f, "CONNECTION LIMIT {expr}")
61            }
62            RoleOption::CreateDB(value) => {
63                write!(f, "{}", if *value { "CREATEDB" } else { "NOCREATEDB" })
64            }
65            RoleOption::CreateRole(value) => {
66                write!(f, "{}", if *value { "CREATEROLE" } else { "NOCREATEROLE" })
67            }
68            RoleOption::Inherit(value) => {
69                write!(f, "{}", if *value { "INHERIT" } else { "NOINHERIT" })
70            }
71            RoleOption::Login(value) => {
72                write!(f, "{}", if *value { "LOGIN" } else { "NOLOGIN" })
73            }
74            RoleOption::Password(password) => match password {
75                Password::Password(expr) => write!(f, "PASSWORD {expr}"),
76                Password::NullPassword => write!(f, "PASSWORD NULL"),
77            },
78            RoleOption::Replication(value) => {
79                write!(
80                    f,
81                    "{}",
82                    if *value {
83                        "REPLICATION"
84                    } else {
85                        "NOREPLICATION"
86                    }
87                )
88            }
89            RoleOption::SuperUser(value) => {
90                write!(f, "{}", if *value { "SUPERUSER" } else { "NOSUPERUSER" })
91            }
92            RoleOption::ValidUntil(expr) => {
93                write!(f, "VALID UNTIL {expr}")
94            }
95        }
96    }
97}
98
99/// SET config value option:
100/// * SET `configuration_parameter` { TO | = } { `value` | DEFAULT }
101/// * SET `configuration_parameter` FROM CURRENT
102#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
104#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
105pub enum SetConfigValue {
106    Default,
107    FromCurrent,
108    Value(Expr),
109}
110
111/// RESET config option:
112/// * RESET `configuration_parameter`
113/// * RESET ALL
114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
117pub enum ResetConfig {
118    ALL,
119    ConfigName(ObjectName),
120}
121
122/// An `ALTER ROLE` (`Statement::AlterRole`) operation
123#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
126pub enum AlterRoleOperation {
127    /// Generic
128    RenameRole {
129        role_name: Ident,
130    },
131    /// MS SQL Server
132    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-role-transact-sql>
133    AddMember {
134        member_name: Ident,
135    },
136    DropMember {
137        member_name: Ident,
138    },
139    /// PostgreSQL
140    /// <https://www.postgresql.org/docs/current/sql-alterrole.html>
141    WithOptions {
142        options: Vec<RoleOption>,
143    },
144    Set {
145        config_name: ObjectName,
146        config_value: SetConfigValue,
147        in_database: Option<ObjectName>,
148    },
149    Reset {
150        config_name: ResetConfig,
151        in_database: Option<ObjectName>,
152    },
153}
154
155impl fmt::Display for AlterRoleOperation {
156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157        match self {
158            AlterRoleOperation::RenameRole { role_name } => {
159                write!(f, "RENAME TO {role_name}")
160            }
161            AlterRoleOperation::AddMember { member_name } => {
162                write!(f, "ADD MEMBER {member_name}")
163            }
164            AlterRoleOperation::DropMember { member_name } => {
165                write!(f, "DROP MEMBER {member_name}")
166            }
167            AlterRoleOperation::WithOptions { options } => {
168                write!(f, "WITH {}", display_separated(options, " "))
169            }
170            AlterRoleOperation::Set {
171                config_name,
172                config_value,
173                in_database,
174            } => {
175                if let Some(database_name) = in_database {
176                    write!(f, "IN DATABASE {} ", database_name)?;
177                }
178
179                match config_value {
180                    SetConfigValue::Default => write!(f, "SET {config_name} TO DEFAULT"),
181                    SetConfigValue::FromCurrent => write!(f, "SET {config_name} FROM CURRENT"),
182                    SetConfigValue::Value(expr) => write!(f, "SET {config_name} TO {expr}"),
183                }
184            }
185            AlterRoleOperation::Reset {
186                config_name,
187                in_database,
188            } => {
189                if let Some(database_name) = in_database {
190                    write!(f, "IN DATABASE {} ", database_name)?;
191                }
192
193                match config_name {
194                    ResetConfig::ALL => write!(f, "RESET ALL"),
195                    ResetConfig::ConfigName(name) => write!(f, "RESET {name}"),
196                }
197            }
198        }
199    }
200}
201
202/// A `USE` (`Statement::Use`) operation
203#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
206pub enum Use {
207    Catalog(ObjectName),            // e.g. `USE CATALOG foo.bar`
208    Schema(ObjectName),             // e.g. `USE SCHEMA foo.bar`
209    Database(ObjectName),           // e.g. `USE DATABASE foo.bar`
210    Warehouse(ObjectName),          // e.g. `USE WAREHOUSE foo.bar`
211    Role(ObjectName),               // e.g. `USE ROLE PUBLIC`
212    SecondaryRoles(SecondaryRoles), // e.g. `USE SECONDARY ROLES ALL`
213    Object(ObjectName),             // e.g. `USE foo.bar`
214    Default,                        // e.g. `USE DEFAULT`
215}
216
217impl fmt::Display for Use {
218    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219        f.write_str("USE ")?;
220        match self {
221            Use::Catalog(name) => write!(f, "CATALOG {}", name),
222            Use::Schema(name) => write!(f, "SCHEMA {}", name),
223            Use::Database(name) => write!(f, "DATABASE {}", name),
224            Use::Warehouse(name) => write!(f, "WAREHOUSE {}", name),
225            Use::Role(name) => write!(f, "ROLE {}", name),
226            Use::SecondaryRoles(secondary_roles) => {
227                write!(f, "SECONDARY ROLES {}", secondary_roles)
228            }
229            Use::Object(name) => write!(f, "{}", name),
230            Use::Default => write!(f, "DEFAULT"),
231        }
232    }
233}
234
235/// Snowflake `SECONDARY ROLES` USE variant
236/// See: <https://docs.snowflake.com/en/sql-reference/sql/use-secondary-roles>
237#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
239#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
240pub enum SecondaryRoles {
241    All,
242    None,
243    List(Vec<Ident>),
244}
245
246impl fmt::Display for SecondaryRoles {
247    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248        match self {
249            SecondaryRoles::All => write!(f, "ALL"),
250            SecondaryRoles::None => write!(f, "NONE"),
251            SecondaryRoles::List(roles) => write!(f, "{}", display_comma_separated(roles)),
252        }
253    }
254}