1use std::fmt::Display;
16use std::fmt::Formatter;
17
18use derive_visitor::Drive;
19use derive_visitor::DriveMut;
20
21use crate::ast::AuthType;
22use crate::ast::CreateOption;
23use crate::ast::PrincipalIdentity;
24use crate::ast::ProcedureIdentity;
25use crate::ast::ShowOptions;
26use crate::ast::UserIdentity;
27use crate::ast::UserPrivilegeType;
28use crate::ast::write_comma_separated_list;
29
30#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
31pub struct CreateUserStmt {
32 pub create_option: CreateOption,
33 pub user: UserIdentity,
34 pub auth_option: AuthOption,
35 pub user_options: Vec<UserOptionItem>,
36}
37
38impl Display for CreateUserStmt {
39 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
40 write!(f, "CREATE")?;
41 if let CreateOption::CreateOrReplace = self.create_option {
42 write!(f, " OR REPLACE")?;
43 }
44 write!(f, " USER")?;
45 if let CreateOption::CreateIfNotExists = self.create_option {
46 write!(f, " IF NOT EXISTS")?;
47 }
48 write!(f, " {} IDENTIFIED", self.user)?;
49 write!(f, " {}", self.auth_option)?;
50 if !self.user_options.is_empty() {
51 write!(f, " WITH ")?;
52 write_comma_separated_list(f, &self.user_options)?;
53 }
54
55 Ok(())
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Default, Drive, DriveMut)]
60pub struct AuthOption {
61 pub auth_type: Option<AuthType>,
62 pub password: Option<String>,
63}
64
65impl Display for AuthOption {
66 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
67 if let Some(auth_type) = &self.auth_type {
68 write!(f, "WITH {auth_type} ")?;
69 }
70 if let Some(password) = &self.password {
71 write!(f, "BY '{password}'")?;
72 }
73
74 Ok(())
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
79pub struct AlterUserStmt {
80 pub user: Option<UserIdentity>,
82 pub auth_option: Option<AuthOption>,
84 pub user_options: Vec<UserOptionItem>,
85}
86
87impl Display for AlterUserStmt {
88 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
89 write!(f, "ALTER USER")?;
90 if let Some(user) = &self.user {
91 write!(f, " {}", user)?;
92 } else {
93 write!(f, " USER()")?;
94 }
95 if let Some(auth_option) = &self.auth_option {
96 write!(f, " IDENTIFIED {}", auth_option)?;
97 }
98 if !self.user_options.is_empty() {
99 write!(f, " WITH ")?;
100 write_comma_separated_list(f, &self.user_options)?;
101 }
102
103 Ok(())
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
108pub struct GrantStmt {
109 pub source: AccountMgrSource,
110 pub principal: PrincipalIdentity,
111}
112
113impl Display for GrantStmt {
114 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
115 write!(f, "GRANT")?;
116 write!(f, "{}", self.source)?;
117
118 write!(f, " TO")?;
119 write!(f, "{}", self.principal)
120 }
121}
122
123#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
124pub struct RevokeStmt {
125 pub source: AccountMgrSource,
126 pub principal: PrincipalIdentity,
127}
128
129impl Display for RevokeStmt {
130 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
131 write!(f, "REVOKE")?;
132 write!(f, "{}", self.source)?;
133
134 write!(f, " FROM")?;
135 write!(f, "{}", self.principal)
136 }
137}
138
139#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
140pub struct ShowGranteesOfRoleStmt {
141 pub name: String,
142 pub show_option: Option<ShowOptions>,
143}
144
145impl Display for ShowGranteesOfRoleStmt {
146 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
147 write!(f, "SHOW GRANTS OF ROLE {}", self.name)?;
148
149 if let Some(show_option) = &self.show_option {
150 write!(f, " {show_option}")?;
151 }
152 Ok(())
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
157pub struct ShowObjectPrivilegesStmt {
158 pub object: GrantObjectName,
159 pub show_option: Option<ShowOptions>,
160}
161
162#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
163pub enum GrantObjectName {
164 Database(String),
165 Table(Option<String>, String),
166 UDF(String),
167 Stage(String),
168 Warehouse(String),
169 Connection(String),
170 Sequence(String),
171 Procedure(ProcedureIdentity),
172 MaskingPolicy(String),
173 RowAccessPolicy(String),
174}
175
176impl Display for GrantObjectName {
177 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
178 match self {
179 GrantObjectName::Database(database_name) => {
180 write!(f, "DATABASE {database_name}")
181 }
182 GrantObjectName::Table(database_name, table_name) => {
183 if let Some(database_name) = database_name {
184 write!(f, "TABLE {database_name}.{table_name}")
185 } else {
186 write!(f, "TABLE {table_name}")
187 }
188 }
189 GrantObjectName::UDF(udf) => write!(f, "UDF {udf}"),
190 GrantObjectName::Stage(stage) => write!(f, "STAGE {stage}"),
191 GrantObjectName::Warehouse(w) => write!(f, "WAREHOUSE {w}"),
192 GrantObjectName::Connection(c) => write!(f, "CONNECTION {c}"),
193 GrantObjectName::Sequence(s) => write!(f, "SEQUENCE {s}"),
194 GrantObjectName::Procedure(p) => write!(f, "PROCEDURE {p}"),
195 GrantObjectName::MaskingPolicy(policy) => write!(f, "MASKING POLICY {policy}"),
196 GrantObjectName::RowAccessPolicy(policy) => write!(f, "ROW ACCESS POLICY {policy}"),
197 }
198 }
199}
200
201impl Display for ShowObjectPrivilegesStmt {
202 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
203 write!(f, "SHOW GRANTS ON {}", self.object)?;
204
205 if let Some(show_option) = &self.show_option {
206 write!(f, " {show_option}")?;
207 }
208 Ok(())
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
213pub enum AccountMgrSource {
214 Role {
215 role: String,
216 },
217 Privs {
218 privileges: Vec<UserPrivilegeType>,
219 level: AccountMgrLevel,
220 },
221 ALL {
222 level: AccountMgrLevel,
223 },
224}
225
226impl Display for AccountMgrSource {
227 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
228 match self {
229 AccountMgrSource::Role { role } => write!(f, " ROLE '{role}'")?,
230 AccountMgrSource::Privs { privileges, level } => {
231 if privileges.len() == 1
232 && privileges[0] == UserPrivilegeType::ApplyMaskingPolicy
233 && matches!(level, AccountMgrLevel::MaskingPolicy(_))
234 && let AccountMgrLevel::MaskingPolicy(policy) = level
235 {
236 write!(f, " APPLY ON MASKING POLICY {policy}")?;
237 return Ok(());
238 }
239 if privileges.len() == 1
240 && privileges[0] == UserPrivilegeType::ApplyRowAccessPolicy
241 && matches!(level, AccountMgrLevel::RowAccessPolicy(_))
242 && let AccountMgrLevel::RowAccessPolicy(policy) = level
243 {
244 write!(f, " APPLY ON ROW ACCESS POLICY {policy}")?;
245 return Ok(());
246 }
247 write!(f, " ")?;
248 write_comma_separated_list(f, privileges.iter().map(|p| p.to_string()))?;
249 write!(f, " ON")?;
250 write!(f, " {}", level)?;
251 }
252 AccountMgrSource::ALL { level, .. } => {
253 write!(f, " ALL PRIVILEGES")?;
254 write!(f, " ON")?;
255 write!(f, " {}", level)?;
256 }
257 }
258 Ok(())
259 }
260}
261
262#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
263pub enum AccountMgrLevel {
264 Global,
265 Database(Option<String>),
266 Table(Option<String>, String),
267 UDF(String),
268 Stage(String),
269 Warehouse(String),
270 Connection(String),
271 Sequence(String),
272 Procedure(ProcedureIdentity),
273 MaskingPolicy(String),
274 RowAccessPolicy(String),
275}
276
277impl Display for AccountMgrLevel {
278 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
279 match self {
280 AccountMgrLevel::Global => write!(f, " *.*"),
281 AccountMgrLevel::Database(database_name) => {
282 if let Some(database_name) = database_name {
283 write!(f, " {database_name}.*")
284 } else {
285 write!(f, " *")
286 }
287 }
288 AccountMgrLevel::Table(database_name, table_name) => {
289 if let Some(database_name) = database_name {
290 write!(f, " {database_name}.{table_name}")
291 } else {
292 write!(f, " {table_name}")
293 }
294 }
295 AccountMgrLevel::UDF(udf) => write!(f, " UDF {udf}"),
296 AccountMgrLevel::Stage(stage) => write!(f, " STAGE {stage}"),
297 AccountMgrLevel::Warehouse(w) => write!(f, " WAREHOUSE {w}"),
298 AccountMgrLevel::Connection(c) => write!(f, " CONNECTION {c}"),
299 AccountMgrLevel::Sequence(s) => write!(f, " SEQUENCE {s}"),
300 AccountMgrLevel::Procedure(p) => write!(f, " PROCEDURE {p}"),
301 AccountMgrLevel::MaskingPolicy(policy) => write!(f, " MASKING POLICY {policy}"),
302 AccountMgrLevel::RowAccessPolicy(policy) => {
303 write!(f, " ROW ACCESS POLICY {policy}")
304 }
305 }
306 }
307}
308
309#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
310pub enum SecondaryRolesOption {
311 None,
312 All,
313 SpecifyRole(Vec<String>),
314}
315
316#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
317pub enum UserOptionItem {
318 TenantSetting(bool),
319 DefaultRole(String),
320 DefaultWarehouse(String),
321 Disabled(bool),
322 SetNetworkPolicy(String),
323 UnsetNetworkPolicy,
324 SetPasswordPolicy(String),
325 UnsetPasswordPolicy,
326 MustChangePassword(bool),
327 SetWorkloadGroup(String),
328 UnsetWorkloadGroup,
329}
330
331impl Display for UserOptionItem {
332 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
333 match self {
334 UserOptionItem::TenantSetting(true) => write!(f, "TENANTSETTING"),
335 UserOptionItem::TenantSetting(false) => write!(f, "NOTENANTSETTING"),
336 UserOptionItem::DefaultRole(v) => write!(f, "DEFAULT_ROLE = '{}'", v),
337 UserOptionItem::DefaultWarehouse(v) => write!(f, "DEFAULT_WAREHOUSE = '{}'", v),
338 UserOptionItem::SetNetworkPolicy(v) => write!(f, "SET NETWORK POLICY = '{}'", v),
339 UserOptionItem::UnsetNetworkPolicy => write!(f, "UNSET NETWORK POLICY"),
340 UserOptionItem::SetPasswordPolicy(v) => write!(f, "SET PASSWORD POLICY = '{}'", v),
341 UserOptionItem::SetWorkloadGroup(v) => write!(f, "SET WORKLOAD GROUP = '{}'", v),
342 UserOptionItem::UnsetWorkloadGroup => write!(f, "UNSET WORKLOAD GROUP"),
343 UserOptionItem::UnsetPasswordPolicy => write!(f, "UNSET PASSWORD POLICY"),
344 UserOptionItem::Disabled(v) => write!(f, "DISABLED = {}", v),
345 UserOptionItem::MustChangePassword(v) => write!(f, "MUST_CHANGE_PASSWORD = {}", v),
346 }
347 }
348}