1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::Display;
use std::fmt::Formatter;

use derive_visitor::Drive;
use derive_visitor::DriveMut;

use crate::ast::quote::QuotedString;
use crate::ast::Identifier;

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub struct ShareNameIdent {
    pub tenant: Identifier,
    pub share: Identifier,
}

impl Display for ShareNameIdent {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}.{}", self.tenant, self.share)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub struct UserIdentity {
    pub username: String,
    pub hostname: String,
}

impl Display for UserIdentity {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}@{}",
            QuotedString(&self.username, '\''),
            QuotedString(&self.hostname, '\''),
        )
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum PrincipalIdentity {
    User(UserIdentity),
    Role(String),
}

impl Display for PrincipalIdentity {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            PrincipalIdentity::User(u) => write!(f, " USER {u}"),
            PrincipalIdentity::Role(r) => write!(f, " ROLE '{r}'"),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum CreateOption {
    Create,
    CreateIfNotExists,
    CreateOrReplace,
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum AuthType {
    NoPassword,
    Sha256Password,
    DoubleSha1Password,
    JWT,
}

impl Display for AuthType {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}", match self {
            AuthType::NoPassword => "no_password",
            AuthType::Sha256Password => "sha256_password",
            AuthType::DoubleSha1Password => "double_sha1_password",
            AuthType::JWT => "jwt",
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum CatalogType {
    Default,
    Hive,
    Iceberg,
    Share,
}

impl Display for CatalogType {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            CatalogType::Default => write!(f, "DEFAULT"),
            CatalogType::Hive => write!(f, "HIVE"),
            CatalogType::Iceberg => write!(f, "ICEBERG"),
            CatalogType::Share => write!(f, "SHARE"),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum UserPrivilegeType {
    // UsagePrivilege is a synonym for “no privileges”, if object is udf, means can use this udf
    Usage,
    // Privilege to select rows from tables in a database.
    Select,
    // Privilege to insert into tables in a database.
    Insert,
    // Privilege to update rows in a table
    Update,
    // Privilege to delete rows in a table
    Delete,
    // Privilege to create databases or tables.
    Create,
    // Privilege to drop databases or tables.
    Drop,
    // Privilege to alter databases or tables.
    Alter,
    // Privilege to Kill query, Set global configs, etc.
    Super,
    // Privilege to Create User.
    CreateUser,
    // Privilege to Create Role.
    CreateRole,
    // Privilege to Grant/Revoke privileges to users or roles
    Grant,
    // Privilege to Create Stage.
    CreateStage,
    // Privilege to Drop role.
    DropRole,
    // Privilege to Drop user.
    DropUser,
    // Privilege to Create/Drop DataMask.
    CreateDataMask,
    // Privilege to Own a databend object such as database/table.
    Ownership,
    // Privilege to Read stage
    Read,
    // Privilege to Write stage
    Write,
    // Privilege to Create database
    CreateDatabase,
    // Discard Privilege Type
    Set,
}

impl Display for UserPrivilegeType {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}", match self {
            UserPrivilegeType::Usage => "USAGE",
            UserPrivilegeType::Create => "CREATE",
            UserPrivilegeType::Update => "UPDATE",
            UserPrivilegeType::Select => "SELECT",
            UserPrivilegeType::Insert => "INSERT",
            UserPrivilegeType::Delete => "DELETE",
            UserPrivilegeType::Drop => "DROP",
            UserPrivilegeType::Alter => "ALTER",
            UserPrivilegeType::Super => "SUPER",
            UserPrivilegeType::CreateUser => "CREATE USER",
            UserPrivilegeType::DropUser => "DROP USER",
            UserPrivilegeType::CreateRole => "CREATE ROLE",
            UserPrivilegeType::DropRole => "DROP ROLE",
            UserPrivilegeType::CreateStage => "CREATE STAGE",
            UserPrivilegeType::Grant => "GRANT",
            UserPrivilegeType::Set => "SET",
            UserPrivilegeType::CreateDataMask => "CREATE DATAMASK",
            UserPrivilegeType::Ownership => "OWNERSHIP",
            UserPrivilegeType::Read => "Read",
            UserPrivilegeType::Write => "Write",
            UserPrivilegeType::CreateDatabase => "CREATE DATABASE",
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum ShareGrantObjectName {
    // database name
    Database(Identifier),
    // database name, table name
    Table(Identifier, Identifier),
    // database name, table name
    View(Identifier, Identifier),
}

impl Display for ShareGrantObjectName {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            ShareGrantObjectName::Database(db) => {
                write!(f, "DATABASE {db}")
            }
            ShareGrantObjectName::Table(db, table) => {
                write!(f, "TABLE {db}.{table}")
            }
            ShareGrantObjectName::View(db, table) => {
                write!(f, "VIEW {db}.{table}")
            }
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum ShareGrantObjectPrivilege {
    // For DATABASE or SCHEMA
    Usage,
    // For DATABASE
    ReferenceUsage,
    // For TABLE or VIEW
    Select,
}

impl Display for ShareGrantObjectPrivilege {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match *self {
            ShareGrantObjectPrivilege::Usage => write!(f, "USAGE"),
            ShareGrantObjectPrivilege::ReferenceUsage => write!(f, "REFERENCE_USAGE"),
            ShareGrantObjectPrivilege::Select => write!(f, "SELECT"),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub struct CopyOptions {
    pub on_error: OnErrorMode,
    pub size_limit: usize,
    pub max_files: usize,
    pub split_size: usize,
    pub purge: bool,
    pub disable_variant_check: bool,
    pub return_failed_only: bool,
    pub max_file_size: usize,
    pub single: bool,
    pub detailed_output: bool,
}

impl Display for CopyOptions {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "OnErrorMode {}", self.on_error)?;
        write!(f, "SizeLimit {}", self.size_limit)?;
        write!(f, "MaxFiles {}", self.max_files)?;
        write!(f, "SplitSize {}", self.split_size)?;
        write!(f, "Purge {}", self.purge)?;
        write!(f, "DisableVariantCheck {}", self.disable_variant_check)?;
        write!(f, "ReturnFailedOnly {}", self.return_failed_only)?;
        write!(f, "MaxFileSize {}", self.max_file_size)?;
        write!(f, "Single {}", self.single)?;
        write!(f, "DetailedOutput {}", self.detailed_output)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
pub enum OnErrorMode {
    Continue,
    SkipFileNum(u64),
    AbortNum(u64),
}

impl Display for OnErrorMode {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            OnErrorMode::Continue => {
                write!(f, "continue")
            }
            OnErrorMode::SkipFileNum(n) => {
                if *n <= 1 {
                    write!(f, "skipfile")
                } else {
                    write!(f, "skipfile_{}", n)
                }
            }
            OnErrorMode::AbortNum(n) => {
                if *n <= 1 {
                    write!(f, "abort")
                } else {
                    write!(f, "abort_{}", n)
                }
            }
        }
    }
}