Skip to content

Commit 2cbff79

Browse files
TCeasonBohuTANG
andauthored
feat(query): support unset session setting (#15510)
* feat(query): support unset session setting Databend now supports the `unset <settings>` command, which is designed to remove global settings from the metasrv. We plan to expand this functionality with additional unset commands: ```sql unset [session] <setting>; -- Only unset a setting at the session level. ``` For example: ``` -- load_file_metadata_expire_hours default is 248 set global load_file_metadata_expire_hours=12; -- show settings like '%load_file_metadata_expire_hours%'; -- 12 global-level set load_file_metadata_expire_hours=13; -- show settings like '%load_file_metadata_expire_hours%'; -- 13 session-level unset session load_file_metadata_expire_hours; -- show settings like '%load_file_metadata_expire_hours%'; -- 12 global-level ``` * optimize code * fix test --------- Co-authored-by: Bohu <overred.shuttler@gmail.com>
1 parent 5de4309 commit 2cbff79

File tree

10 files changed

+149
-21
lines changed

10 files changed

+149
-21
lines changed

src/query/ast/src/ast/format/ast_format.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,11 @@ impl<'ast> Visitor<'ast> for AstFormatVisitor {
10481048
}
10491049

10501050
fn visit_unset_variable(&mut self, stmt: &'ast UnSetStmt) {
1051-
let name = format!("UnSet {}", stmt);
1051+
let name = if stmt.session_level {
1052+
format!("UnSet SESSION {}", stmt)
1053+
} else {
1054+
format!("UnSet {}", stmt)
1055+
};
10521056
let format_ctx = AstFormatContext::new(name);
10531057
let node = FormatTreeNode::new(format_ctx);
10541058
self.children.push(node);

src/query/ast/src/ast/statements/unset.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@ use crate::ast::Identifier;
2323

2424
#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
2525
pub struct UnSetStmt {
26+
#[drive(skip)]
27+
pub session_level: bool,
2628
pub source: UnSetSource,
2729
}
2830

2931
impl Display for UnSetStmt {
3032
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
3133
write!(f, "UNSET ")?;
34+
if self.session_level {
35+
write!(f, "SESSION ")?;
36+
}
3237
write!(f, "{}", self.source)
3338
}
3439
}

src/query/ast/src/parser/statement.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,11 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
362362

363363
let unset_variable = map(
364364
rule! {
365-
UNSET ~ #unset_source
365+
UNSET ~ SESSION? ~ #unset_source
366366
},
367-
|(_, unset_source)| {
367+
|(_, opt_session_level, unset_source)| {
368368
Statement::UnSetVariable(UnSetStmt {
369+
session_level: opt_session_level.is_some(),
369370
source: unset_source,
370371
})
371372
},

src/query/ast/src/parser/token.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,8 @@ pub enum TokenKind {
980980
SET,
981981
#[token("UNSET", ignore(ascii_case))]
982982
UNSET,
983+
#[token("SESSION", ignore(ascii_case))]
984+
SESSION,
983985
#[token("SETTINGS", ignore(ascii_case))]
984986
SETTINGS,
985987
#[token("STAGES", ignore(ascii_case))]

src/query/ast/tests/it/parser.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,9 @@ fn test_statement() {
569569
r#"SET max_threads = 10;"#,
570570
r#"SET max_threads = 10*2;"#,
571571
r#"UNSET max_threads;"#,
572+
r#"UNSET session max_threads;"#,
572573
r#"UNSET (max_threads, sql_dialect);"#,
574+
r#"UNSET session (max_threads, sql_dialect);"#,
573575
r#"select $1 FROM '@my_stage/my data/'"#,
574576
r#"
575577
SELECT t.c1 FROM @stage1/dir/file

src/query/ast/tests/it/testdata/statement.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14988,6 +14988,7 @@ UNSET max_threads
1498814988
---------- AST ------------
1498914989
UnSetVariable(
1499014990
UnSetStmt {
14991+
session_level: false,
1499114992
source: Var {
1499214993
variable: Identifier {
1499314994
span: Some(
@@ -15002,13 +15003,36 @@ UnSetVariable(
1500215003
)
1500315004

1500415005

15006+
---------- Input ----------
15007+
UNSET session max_threads;
15008+
---------- Output ---------
15009+
UNSET SESSION max_threads
15010+
---------- AST ------------
15011+
UnSetVariable(
15012+
UnSetStmt {
15013+
session_level: true,
15014+
source: Var {
15015+
variable: Identifier {
15016+
span: Some(
15017+
14..25,
15018+
),
15019+
name: "max_threads",
15020+
quote: None,
15021+
is_hole: false,
15022+
},
15023+
},
15024+
},
15025+
)
15026+
15027+
1500515028
---------- Input ----------
1500615029
UNSET (max_threads, sql_dialect);
1500715030
---------- Output ---------
1500815031
UNSET (max_threads, sql_dialect)
1500915032
---------- AST ------------
1501015033
UnSetVariable(
1501115034
UnSetStmt {
15035+
session_level: false,
1501215036
source: Vars {
1501315037
variables: [
1501415038
Identifier {
@@ -15033,6 +15057,38 @@ UnSetVariable(
1503315057
)
1503415058

1503515059

15060+
---------- Input ----------
15061+
UNSET session (max_threads, sql_dialect);
15062+
---------- Output ---------
15063+
UNSET SESSION (max_threads, sql_dialect)
15064+
---------- AST ------------
15065+
UnSetVariable(
15066+
UnSetStmt {
15067+
session_level: true,
15068+
source: Vars {
15069+
variables: [
15070+
Identifier {
15071+
span: Some(
15072+
15..26,
15073+
),
15074+
name: "max_threads",
15075+
quote: None,
15076+
is_hole: false,
15077+
},
15078+
Identifier {
15079+
span: Some(
15080+
28..39,
15081+
),
15082+
name: "sql_dialect",
15083+
quote: None,
15084+
is_hole: false,
15085+
},
15086+
],
15087+
},
15088+
},
15089+
)
15090+
15091+
1503615092
---------- Input ----------
1503715093
select $1 FROM '@my_stage/my data/'
1503815094
---------- Output ---------

src/query/service/src/interpreters/interpreter_unsetting.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::sync::Arc;
1717
use databend_common_config::GlobalConfig;
1818
use databend_common_exception::Result;
1919
use databend_common_sql::plans::UnSettingPlan;
20+
use databend_common_users::UserApiProvider;
2021

2122
use crate::interpreters::Interpreter;
2223
use crate::pipelines::PipelineBuildResult;
@@ -51,18 +52,29 @@ impl Interpreter for UnSettingInterpreter {
5152
let mut keys: Vec<String> = vec![];
5253
let mut values: Vec<String> = vec![];
5354
let mut is_globals: Vec<bool> = vec![];
54-
5555
let settings = self.ctx.get_shared_settings();
56+
let session_level = self.set.session_level;
57+
settings.load_changes().await?;
58+
59+
// Fetch global settings asynchronously if necessary
60+
let global_settings = if !session_level {
61+
UserApiProvider::instance()
62+
.setting_api(&self.ctx.get_tenant())
63+
.get_settings()
64+
.await?
65+
} else {
66+
Vec::new()
67+
};
68+
5669
for var in plan.vars {
5770
let (ok, value) = match var.to_lowercase().as_str() {
5871
// To be compatible with some drivers
5972
"sql_mode" | "autocommit" => (false, String::from("")),
6073
setting_key => {
6174
// TODO(liyz): why drop the global setting without checking the variable is global or not?
62-
self.ctx
63-
.get_shared_settings()
64-
.try_drop_global_setting(setting_key)
65-
.await?;
75+
if !session_level {
76+
settings.try_drop_global_setting(setting_key).await?;
77+
}
6678

6779
let default_val = match setting_key {
6880
"max_memory_usage" => {
@@ -90,7 +102,23 @@ impl Interpreter for UnSettingInterpreter {
90102
.map(|v| v.to_string()),
91103
};
92104
match default_val {
93-
Some(val) => (true, val),
105+
Some(val) => {
106+
let final_val = if global_settings.is_empty() {
107+
val.to_string()
108+
} else {
109+
global_settings
110+
.iter()
111+
.find(|setting| setting.name.to_lowercase() == setting_key)
112+
.map_or(
113+
{
114+
self.ctx.get_shared_settings().unset_setting(&var);
115+
val.to_string()
116+
},
117+
|setting| setting.value.to_string(),
118+
)
119+
};
120+
(true, final_val)
121+
}
94122
None => {
95123
self.ctx
96124
.push_warning(format!("Unknown setting: '{}'", setting_key));
@@ -100,8 +128,6 @@ impl Interpreter for UnSettingInterpreter {
100128
}
101129
};
102130
if ok {
103-
// reset the current ctx settings, just remove it.
104-
self.ctx.get_shared_settings().unset_setting(&var);
105131
// set effect, this can be considered to be removed in the future.
106132
keys.push(var);
107133
values.push(value);

src/query/sql/src/planner/binder/setting.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,24 @@ impl Binder {
7575
_bind_context: &BindContext,
7676
stmt: &UnSetStmt,
7777
) -> Result<Plan> {
78+
let session_level = stmt.session_level;
7879
match &stmt.source {
7980
UnSetSource::Var { variable } => {
8081
let vars = vec![variable.name.to_lowercase()];
81-
Ok(Plan::UnSetVariable(Box::new(UnSettingPlan { vars })))
82+
Ok(Plan::UnSetVariable(Box::new(UnSettingPlan {
83+
session_level,
84+
vars,
85+
})))
8286
}
8387
UnSetSource::Vars { variables } => {
8488
let vars: Vec<String> = variables
8589
.iter()
8690
.map(|var| var.name.to_lowercase())
8791
.collect();
88-
Ok(Plan::UnSetVariable(Box::new(UnSettingPlan { vars })))
92+
Ok(Plan::UnSetVariable(Box::new(UnSettingPlan {
93+
session_level,
94+
vars,
95+
})))
8996
}
9097
}
9198
}

src/query/sql/src/planner/plans/setting.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ pub struct SettingPlan {
2626

2727
#[derive(Clone, Debug, PartialEq, Eq)]
2828
pub struct UnSettingPlan {
29+
pub session_level: bool,
2930
pub vars: Vec<String>,
3031
}

tests/sqllogictests/suites/base/05_ddl/05_0026_ddl_unset_settings.test

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,33 @@
1-
onlyif mysql
21
query TTTT
32
SELECT name, value, default, level from system.settings where name in ('sql_dialect', 'timezone')
43
----
54
sql_dialect PostgreSQL PostgreSQL DEFAULT
65
timezone UTC UTC DEFAULT
76

8-
onlyif mysql
97
statement ok
108
SET GLOBAL sql_dialect='MySQL'
119

12-
onlyif mysql
1310
statement ok
1411
SET GLOBAL timezone='Asia/Shanghai'
1512

16-
onlyif mysql
1713
query TTTT
1814
SELECT name, value, default, level from system.settings where name in ('sql_dialect', 'timezone')
1915
----
2016
sql_dialect MySQL PostgreSQL GLOBAL
2117
timezone Asia/Shanghai UTC GLOBAL
2218

23-
onlyif mysql
2419
statement ok
2520
UNSET (timezone)
2621

27-
onlyif mysql
2822
statement error 2801
2923
SET stl_dialect='MySQL'
3024

3125
statement ok
3226
UNSET stl_dialect
3327

34-
onlyif mysql
3528
statement ok
3629
UNSET sql_dialect
3730

38-
onlyif mysql
3931
query TTTT
4032
SELECT name, value, default, level from system.settings where name in ('sql_dialect', 'timezone')
4133
----
@@ -58,3 +50,35 @@ show settings like 'DATA_RETENTION_TIME_IN_DAYS';
5850
----
5951
data_retention_time_in_days 1 1 [0, 90] DEFAULT Sets the data retention time in days. UInt64
6052

53+
statement ok
54+
set global load_file_metadata_expire_hours=12;
55+
56+
query TT
57+
show settings like 'load_file_metadata_expire_hours';
58+
----
59+
load_file_metadata_expire_hours 12 24 [0, 18446744073709551615] GLOBAL Sets the hours that the metadata of files you load data from with COPY INTO will expire in. UInt64
60+
61+
statement ok
62+
set load_file_metadata_expire_hours=13;
63+
64+
query TTTTTTT
65+
show settings like 'load_file_metadata_expire_hours';
66+
----
67+
load_file_metadata_expire_hours 13 24 [0, 18446744073709551615] SESSION Sets the hours that the metadata of files you load data from with COPY INTO will expire in. UInt64
68+
69+
statement ok
70+
unset session load_file_metadata_expire_hours;
71+
72+
query TTTTTTT
73+
show settings like 'load_file_metadata_expire_hours';
74+
----
75+
load_file_metadata_expire_hours 12 24 [0, 18446744073709551615] GLOBAL Sets the hours that the metadata of files you load data from with COPY INTO will expire in. UInt64
76+
77+
statement ok
78+
unset load_file_metadata_expire_hours
79+
80+
query TTTTTTT
81+
show settings like 'load_file_metadata_expire_hours';
82+
----
83+
load_file_metadata_expire_hours 24 24 [0, 18446744073709551615] DEFAULT Sets the hours that the metadata of files you load data from with COPY INTO will expire in. UInt64
84+

0 commit comments

Comments
 (0)