Skip to content

Commit e87d736

Browse files
authored
Merge branch 'main' into fix/cluster_hang_3
2 parents baddb7a + 49da701 commit e87d736

File tree

78 files changed

+2702
-2767
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2702
-2767
lines changed

.github/actions/setup_bendsql/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ inputs:
44
version:
55
description: "bendsql version"
66
required: false
7-
default: v0.3.8
7+
default: v0.3.9
88
runs:
99
using: "composite"
1010
steps:

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/clickbench/tpch/queries.sql

Lines changed: 20 additions & 20 deletions
Large diffs are not rendered by default.

docs/doc/15-sql-functions/11-conditional-functions/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ title: 'Conditional Functions'
44

55
| Function | Description | Example | Result |
66
|------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|----------|
7-
| **IF(expr1, expr2, expr3)** | Return expr2 if expr1 is TRUE. Otherwise return expr3. expr2 and expr3 must have the lowest common type. | **IF(1 > 2, 3, 4)** | 4 |
7+
| **IF(cond1, expr1, [cond2, expr2, ...], expr_else)** | If cond1 is TRUE, it returns expr1. Otherwise if cond2 is TRUE, it returns expr2, and so on. | **IF(1 > 2, 3, 4 < 5, 6, 7)** | 6 |
88
| **IFNULL(expr1, expr2)** | Return expr1 if it is not NULL. Otherwise return expr2. They must have the same data type. | **IFNULL(0, NULL)** | 0 |
99
| **value [ NOT ] IN (value1, value2, ...)** | Check whether value is (or is not) one of the members of an explicit list. | **1 not in (2, 3)** | 1(TRUE) |
1010
| **expr1 IS [ NOT ] DISTINCT FROM expr2** | Compares whether two expressions are equal (or not equal) with awareness of nullability, meaning it treats NULLs as known values for comparing equality. | **NULL is distinct from NULL** | 0(FALSE) |
1111
| **IS_NOT_NULL(expr)** | Check whether the value is not NULL. | **IS_NOT_NULL(1)** | 1(TRUE) |
1212
| **IS_NULL(expr)** | Check whether the value is NULL. | **IS_NULL(1)** | 0(FALSE) |
13-
| **MULTI_IF(cond1, expr1, [cond2, expr2, ...], expr_else)** | If cond1 is TRUE, it returns expr1. Otherwise if cond2 is TRUE, it returns expr2, and so on. | **MULTI_IF(1 > 2, 3, 4 < 5, 6, 7)** | 6 |
1413
| **NULLIF(expr1, expr2)** | Return NULL if two expressions are equal. Otherwise return expr1. They must have the same data type. | **NULLIF(0, NULL)** | 0 |

scripts/benchmark/query/load/tpch10.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ select version();
77
SQL
88

99
for t in customer lineitem nation orders partsupp part region supplier; do
10-
echo "DROP TABLE IF EXISTS $t;" | bendsql query
10+
echo "DROP TABLE IF EXISTS $t;" | bendsql query
1111
done
1212

1313
cat <<SQL | bendsql query
@@ -113,8 +113,8 @@ cat <<SQL | bendsql query
113113
SQL
114114

115115
for t in customer lineitem nation orders partsupp part region supplier; do
116-
echo "loading into $t ..."
117-
cat <<SQL | bendsql query
116+
echo "loading into $t ..."
117+
cat <<SQL | bendsql query
118118
COPY INTO $t FROM 's3://repo.databend.rs/datasets/tpch10/${t}/'
119119
credentials=(aws_key_id='$REPO_ACCESS_KEY_ID' aws_secret_key='$REPO_SECRET_ACCESS_KEY') pattern ='${t}.*'
120120
file_format=(type='CSV' field_delimiter='|' record_delimiter='\\n' skip_header=0);

src/common/storage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ anyhow = { workspace = true }
2121
async-trait = "0.1"
2222
bytes = "1"
2323
chrono = { workspace = true }
24+
flagset = "0.4"
2425
futures = "0.3"
2526
opendal = { workspace = true }
2627
regex = "1.6.0"

src/common/storage/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ pub use parquet::read_parquet_schema_async;
5555

5656
mod stage;
5757
pub use stage::init_stage_operator;
58-
pub use stage::FileWithMeta;
5958
pub use stage::StageFileInfo;
6059
pub use stage::StageFileStatus;
6160
pub use stage::StageFilesInfo;

src/common/storage/src/stage.rs

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,6 @@ use regex::Regex;
3333
use crate::init_operator;
3434
use crate::DataOperator;
3535

36-
pub struct FileWithMeta {
37-
pub path: String,
38-
pub metadata: Metadata,
39-
}
40-
41-
impl FileWithMeta {
42-
fn new(path: &str, meta: Metadata) -> Self {
43-
Self {
44-
path: path.to_string(),
45-
metadata: meta,
46-
}
47-
}
48-
}
49-
5036
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
5137
pub enum StageFileStatus {
5238
NeedCopy,
@@ -79,11 +65,10 @@ impl StageFileInfo {
7965
creator: None,
8066
}
8167
}
82-
}
8368

84-
impl From<FileWithMeta> for StageFileInfo {
85-
fn from(value: FileWithMeta) -> Self {
86-
StageFileInfo::new(value.path, &value.metadata)
69+
/// NOTE: update this query when add new meta
70+
pub fn meta_query() -> flagset::FlagSet<Metakey> {
71+
Metakey::ContentLength | Metakey::ContentMd5 | Metakey::LastModified | Metakey::Etag
8772
}
8873
}
8974

@@ -122,7 +107,7 @@ impl StageFilesInfo {
122107
}
123108
}
124109

125-
pub async fn list(&self, operator: &Operator, first_only: bool) -> Result<Vec<FileWithMeta>> {
110+
pub async fn list(&self, operator: &Operator, first_only: bool) -> Result<Vec<StageFileInfo>> {
126111
if let Some(files) = &self.files {
127112
let mut res = Vec::new();
128113
for file in files {
@@ -132,7 +117,7 @@ impl StageFilesInfo {
132117
.to_string();
133118
let meta = operator.stat(&full_path).await?;
134119
if meta.mode().is_file() {
135-
res.push(FileWithMeta::new(&full_path, meta))
120+
res.push(StageFileInfo::new(full_path, &meta))
136121
} else {
137122
return Err(ErrorCode::BadArguments(format!(
138123
"{full_path} is not a file"
@@ -149,15 +134,15 @@ impl StageFilesInfo {
149134
}
150135
}
151136

152-
pub async fn first_file(&self, operator: &Operator) -> Result<FileWithMeta> {
137+
pub async fn first_file(&self, operator: &Operator) -> Result<StageFileInfo> {
153138
let mut files = self.list(operator, true).await?;
154139
match files.pop() {
155140
None => Err(ErrorCode::BadArguments("no file found")),
156141
Some(f) => Ok(f),
157142
}
158143
}
159144

160-
pub fn blocking_first_file(&self, operator: &Operator) -> Result<FileWithMeta> {
145+
pub fn blocking_first_file(&self, operator: &Operator) -> Result<StageFileInfo> {
161146
let mut files = self.blocking_list(operator, true)?;
162147
match files.pop() {
163148
None => Err(ErrorCode::BadArguments("no file found")),
@@ -169,7 +154,7 @@ impl StageFilesInfo {
169154
&self,
170155
operator: &Operator,
171156
first_only: bool,
172-
) -> Result<Vec<FileWithMeta>> {
157+
) -> Result<Vec<StageFileInfo>> {
173158
if let Some(files) = &self.files {
174159
let mut res = Vec::new();
175160
for file in files {
@@ -179,7 +164,7 @@ impl StageFilesInfo {
179164
.to_string();
180165
let meta = operator.blocking().stat(&full_path)?;
181166
if meta.mode().is_file() {
182-
res.push(FileWithMeta::new(&full_path, meta))
167+
res.push(StageFileInfo::new(full_path, &meta))
183168
} else {
184169
return Err(ErrorCode::BadArguments(format!(
185170
"{full_path} is not a file"
@@ -201,11 +186,11 @@ impl StageFilesInfo {
201186
path: &str,
202187
pattern: Option<Regex>,
203188
first_only: bool,
204-
) -> Result<Vec<FileWithMeta>> {
189+
) -> Result<Vec<StageFileInfo>> {
205190
let root_meta = operator.stat(path).await;
206191
match root_meta {
207192
Ok(meta) => match meta.mode() {
208-
EntryMode::FILE => return Ok(vec![FileWithMeta::new(path, meta)]),
193+
EntryMode::FILE => return Ok(vec![StageFileInfo::new(path.to_string(), &meta)]),
209194
EntryMode::DIR => {}
210195
EntryMode::Unknown => {
211196
return Err(ErrorCode::BadArguments("object mode is unknown"));
@@ -224,10 +209,9 @@ impl StageFilesInfo {
224209
let mut files = Vec::new();
225210
let mut list = operator.scan(path).await?;
226211
while let Some(obj) = list.try_next().await? {
227-
// todo(youngsofun): not always need Metakey::Complete
228-
let meta = operator.metadata(&obj, Metakey::Complete).await?;
212+
let meta = operator.metadata(&obj, StageFileInfo::meta_query()).await?;
229213
if check_file(obj.path(), meta.mode(), &pattern) {
230-
files.push(FileWithMeta::new(obj.path(), meta));
214+
files.push(StageFileInfo::new(obj.path().to_string(), &meta));
231215
if first_only {
232216
return Ok(files);
233217
}
@@ -253,13 +237,13 @@ fn blocking_list_files_with_pattern(
253237
path: &str,
254238
pattern: Option<Regex>,
255239
first_only: bool,
256-
) -> Result<Vec<FileWithMeta>> {
240+
) -> Result<Vec<StageFileInfo>> {
257241
let operator = operator.blocking();
258242

259243
let root_meta = operator.stat(path);
260244
match root_meta {
261245
Ok(meta) => match meta.mode() {
262-
EntryMode::FILE => return Ok(vec![FileWithMeta::new(path, meta)]),
246+
EntryMode::FILE => return Ok(vec![StageFileInfo::new(path.to_string(), &meta)]),
263247
EntryMode::DIR => {}
264248
EntryMode::Unknown => return Err(ErrorCode::BadArguments("object mode is unknown")),
265249
},
@@ -277,9 +261,9 @@ fn blocking_list_files_with_pattern(
277261
let list = operator.list(path)?;
278262
for obj in list {
279263
let obj = obj?;
280-
let meta = operator.metadata(&obj, Metakey::Complete)?;
264+
let meta = operator.metadata(&obj, StageFileInfo::meta_query())?;
281265
if check_file(obj.path(), meta.mode(), &pattern) {
282-
files.push(FileWithMeta::new(obj.path(), meta));
266+
files.push(StageFileInfo::new(obj.path().to_string(), &meta));
283267
if first_only {
284268
return Ok(files);
285269
}

src/meta/app/src/principal/user_grant.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,21 @@ impl GrantEntry {
9090
&self.privileges
9191
}
9292

93-
pub fn verify_privilege(&self, object: &GrantObject, privilege: UserPrivilegeType) -> bool {
93+
pub fn verify_privilege(
94+
&self,
95+
object: &GrantObject,
96+
privileges: Vec<UserPrivilegeType>,
97+
) -> bool {
9498
// the verified object should be smaller than the object inside my grant entry.
9599
if !self.object.contains(object) {
96100
return false;
97101
}
98102

99-
self.privileges.contains(privilege)
103+
let mut priv_set = UserPrivilegeSet::empty();
104+
for privilege in privileges {
105+
priv_set.set_privilege(privilege)
106+
}
107+
self.privileges.contains(BitFlags::from(priv_set))
100108
}
101109

102110
pub fn matches_entry(&self, object: &GrantObject) -> bool {
@@ -156,10 +164,14 @@ impl UserGrantSet {
156164
self.roles.remove(role);
157165
}
158166

159-
pub fn verify_privilege(&self, object: &GrantObject, privilege: UserPrivilegeType) -> bool {
167+
pub fn verify_privilege(
168+
&self,
169+
object: &GrantObject,
170+
privilege: Vec<UserPrivilegeType>,
171+
) -> bool {
160172
self.entries
161173
.iter()
162-
.any(|e| e.verify_privilege(object, privilege))
174+
.any(|e| e.verify_privilege(object, privilege.clone()))
163175
}
164176

165177
pub fn grant_privileges(&mut self, object: &GrantObject, privileges: UserPrivilegeSet) {

src/meta/app/src/principal/user_privilege.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ pub enum UserPrivilegeType {
5858
Grant = 1 << 12,
5959
// Privilege to Create Stage.
6060
CreateStage = 1 << 13,
61+
// Privilege to Drop role.
62+
DropRole = 1 << 14,
63+
// Privilege to Drop user.
64+
DropUser = 1 << 15,
6165
// TODO: remove this later
6266
Set = 1 << 4,
6367
}
@@ -73,7 +77,9 @@ const ALL_PRIVILEGES: BitFlags<UserPrivilegeType> = make_bitflags!(
7377
| Alter
7478
| Super
7579
| CreateUser
80+
| DropUser
7681
| CreateRole
82+
| DropRole
7783
| Grant
7884
| CreateStage
7985
| Set
@@ -93,7 +99,9 @@ impl std::fmt::Display for UserPrivilegeType {
9399
UserPrivilegeType::Alter => "ALTER",
94100
UserPrivilegeType::Super => "SUPER",
95101
UserPrivilegeType::CreateUser => "CREATE USER",
102+
UserPrivilegeType::DropUser => "DROP USER",
96103
UserPrivilegeType::CreateRole => "CREATE ROLE",
104+
UserPrivilegeType::DropRole => "DROP ROLE",
97105
UserPrivilegeType::CreateStage => "CREATE STAGE",
98106
UserPrivilegeType::Grant => "GRANT",
99107
UserPrivilegeType::Set => "SET",
@@ -121,8 +129,7 @@ impl UserPrivilegeSet {
121129
/// on databases and tables, and has some Global only privileges.
122130
pub fn available_privileges_on_global() -> Self {
123131
let database_privs = Self::available_privileges_on_database();
124-
let privs =
125-
make_bitflags!(UserPrivilegeType::{ Usage | Super | CreateUser | CreateRole | Grant });
132+
let privs = make_bitflags!(UserPrivilegeType::{ Usage | Super | CreateUser | DropUser | CreateRole | DropRole | Grant });
126133
(database_privs.privileges | privs).into()
127134
}
128135

0 commit comments

Comments
 (0)