diff --git a/.github/workflows/databend-auto-tag.yml b/.github/workflows/databend-auto-tag.yml index a7c863d08e16..c8aae2587c5c 100644 --- a/.github/workflows/databend-auto-tag.yml +++ b/.github/workflows/databend-auto-tag.yml @@ -3,7 +3,7 @@ name: Auto tag for nightly release on: schedule: # Release at 00:00 UTC+8 - - cron: '0 16 * * *' + - cron: '0 16 * * *' workflow_dispatch: permissions: diff --git a/common/ast/src/ast/statements/show.rs b/common/ast/src/ast/statements/show.rs index 6b2a4102ab7d..ad25f278b076 100644 --- a/common/ast/src/ast/statements/show.rs +++ b/common/ast/src/ast/statements/show.rs @@ -26,7 +26,7 @@ pub enum ShowLimit<'a> { impl<'a> Display for ShowLimit<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - ShowLimit::Like { pattern } => write!(f, "LIKE {pattern}"), + ShowLimit::Like { pattern } => write!(f, "LIKE '{pattern}'"), ShowLimit::Where { selection } => write!(f, "WHERE {selection}"), } } diff --git a/common/ast/src/ast/statements/statement.rs b/common/ast/src/ast/statements/statement.rs index 437080523f8c..7c32dc7964a2 100644 --- a/common/ast/src/ast/statements/statement.rs +++ b/common/ast/src/ast/statements/statement.rs @@ -37,7 +37,9 @@ pub enum Statement<'a> { Copy(CopyStmt<'a>), Call(CallStmt), - ShowSettings, + ShowSettings { + like: Option, + }, ShowProcessList, ShowMetrics, ShowFunctions { @@ -186,7 +188,12 @@ impl<'a> Display for Statement<'a> { } } Statement::Copy(stmt) => write!(f, "{stmt}")?, - Statement::ShowSettings => {} + Statement::ShowSettings { like } => { + write!(f, "SHOW SETTINGS")?; + if like.is_some() { + write!(f, " LIKE '{}'", like.as_ref().unwrap())?; + } + } Statement::ShowProcessList => write!(f, "SHOW PROCESSLIST")?, Statement::ShowMetrics => write!(f, "SHOW METRICS")?, Statement::ShowFunctions { limit } => { diff --git a/common/ast/src/parser/statement.rs b/common/ast/src/parser/statement.rs index 79311a2de084..fe06e5eec6c8 100644 --- a/common/ast/src/parser/statement.rs +++ b/common/ast/src/parser/statement.rs @@ -81,7 +81,14 @@ pub fn statement(i: Input) -> IResult { selection: opt_where_block.map(|(_, selection)| selection), }, ); - let show_settings = value(Statement::ShowSettings, rule! { SHOW ~ SETTINGS }); + let show_settings = map( + rule! { + SHOW ~ SETTINGS ~ (LIKE ~ #literal_string)? + }, + |(_, _, opt_like)| Statement::ShowSettings { + like: opt_like.map(|(_, like)| like), + }, + ); let show_stages = value(Statement::ShowStages, rule! { SHOW ~ STAGES }); let show_process_list = value(Statement::ShowProcessList, rule! { SHOW ~ PROCESSLIST }); let show_metrics = value(Statement::ShowMetrics, rule! { SHOW ~ METRICS }); @@ -689,7 +696,7 @@ pub fn statement(i: Input) -> IResult { | #explain : "`EXPLAIN [PIPELINE | GRAPH] `" | #insert : "`INSERT INTO [TABLE] [(, ...)] (FORMAT | VALUES | )`" | #delete : "`DELETE FROM
[WHERE ...]`" - | #show_settings : "`SHOW SETTINGS`" + | #show_settings : "`SHOW SETTINGS []`" | #show_stages : "`SHOW STAGES`" | #show_process_list : "`SHOW PROCESSLIST`" | #show_metrics : "`SHOW METRICS`" diff --git a/common/ast/tests/it/parser.rs b/common/ast/tests/it/parser.rs index 7088f976fa06..5dee62d38a57 100644 --- a/common/ast/tests/it/parser.rs +++ b/common/ast/tests/it/parser.rs @@ -211,6 +211,7 @@ fn test_statement() { size_limit=10;"#, r#"CALL system$test(a)"#, r#"CALL system$test('a')"#, + r#"show settings like 'enable%'"#, ]; for case in cases { @@ -264,6 +265,7 @@ fn test_statement_error() { r#"COPY INTO mytable FROM @mystage CREDENTIALS = ();"#, r#"CALL system$test"#, r#"CALL system$test(a"#, + r#"show settings ilike 'enable%'"#, ]; for case in cases { diff --git a/common/ast/tests/it/testdata/statement-error.txt b/common/ast/tests/it/testdata/statement-error.txt index aa7018444bb0..b95a41504595 100644 --- a/common/ast/tests/it/testdata/statement-error.txt +++ b/common/ast/tests/it/testdata/statement-error.txt @@ -304,3 +304,13 @@ error: | while parsing `CALL (, ...)` +---------- Input ---------- +show settings ilike 'enable%' +---------- Output --------- +error: + --> SQL:1:15 + | +1 | show settings ilike 'enable%' + | ^^^^^ expected `LIKE`, `FORMAT`, or `;` + + diff --git a/common/ast/tests/it/testdata/statement.txt b/common/ast/tests/it/testdata/statement.txt index 41df2e7164fe..39454f36aefe 100644 --- a/common/ast/tests/it/testdata/statement.txt +++ b/common/ast/tests/it/testdata/statement.txt @@ -4755,3 +4755,15 @@ Call( ) +---------- Input ---------- +show settings like 'enable%' +---------- Output --------- +SHOW SETTINGS LIKE 'enable%' +---------- AST ------------ +ShowSettings { + like: Some( + "enable%", + ), +} + + diff --git a/query/src/sql/planner/binder/mod.rs b/query/src/sql/planner/binder/mod.rs index 0f9fe00d68bd..1676abbb089b 100644 --- a/query/src/sql/planner/binder/mod.rs +++ b/query/src/sql/planner/binder/mod.rs @@ -118,7 +118,7 @@ impl<'a> Binder { Statement::ShowMetrics => Plan::ShowMetrics, Statement::ShowProcessList => Plan::ShowProcessList, - Statement::ShowSettings => Plan::ShowSettings, + Statement::ShowSettings { like } => self.bind_show_settings(bind_context, like).await?, // Databases Statement::ShowDatabases(stmt) => self.bind_show_databases(stmt).await?, diff --git a/query/src/sql/planner/binder/show.rs b/query/src/sql/planner/binder/show.rs index 3850394c7c4b..5211777f0dd3 100644 --- a/query/src/sql/planner/binder/show.rs +++ b/query/src/sql/planner/binder/show.rs @@ -23,7 +23,7 @@ use crate::sql::BindContext; use crate::sql::Binder; impl<'a> Binder { - pub(super) async fn bind_show_functions( + pub(in crate::sql::planner::binder) async fn bind_show_functions( &mut self, bind_context: &BindContext, limit: &Option>, @@ -51,4 +51,21 @@ impl<'a> Binder { let (stmt, _) = parse_sql(&tokens, &backtrace)?; self.bind_statement(bind_context, &stmt).await } + + pub(in crate::sql::planner::binder) async fn bind_show_settings( + &mut self, + bind_context: &BindContext, + like: &Option, + ) -> Result { + let sub_query = like + .clone() + .map(|s| format!("WHERE name LIKE '{s}'")) + .unwrap_or_else(|| "".to_string()); + let query = format!("SELECT name, value, default, level, description, type FROM system.settings {} ORDER BY name", sub_query); + + let tokens = tokenize_sql(query.as_str())?; + let backtrace = Backtrace::new(); + let (stmt, _) = parse_sql(&tokens, &backtrace)?; + self.bind_statement(bind_context, &stmt).await + } } diff --git a/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.result b/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.result new file mode 100644 index 000000000000..0e4081fdbdfe --- /dev/null +++ b/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.result @@ -0,0 +1,19 @@ +compression None None SESSION Format compression, default value: None String +empty_as_default 1 1 SESSION Format empty_as_default, default value: 1 UInt64 +enable_async_insert 0 0 SESSION Whether the client open async insert mode, default value: 0 UInt64 +enable_new_processor_framework 1 1 SESSION Enable new processor framework if value != 0, default value: 1 UInt64 +enable_planner_v2 1 0 SESSION Enable planner v2 by setting this variable to 1, default value: 0 UInt64 +field_delimiter , , SESSION Format field delimiter, default value: , String +flight_client_timeout 60 60 SESSION Max duration the flight client request is allowed to take in seconds. By default, it is 60 seconds UInt64 +group_by_two_level_threshold 10000 10000 SESSION The threshold of keys to open two-level aggregation, default value: 10000 UInt64 +max_block_size 10000 10000 SESSION Maximum block size for reading UInt64 +max_threads 11 16 SESSION The maximum number of threads to execute the request. By default, it is determined automatically. UInt64 +record_delimiter \n \n SESSION Format record_delimiter, default value: \n String +skip_header 0 0 SESSION Whether to skip the input header, default value: 0 UInt64 +storage_read_buffer_size 1048576 1048576 SESSION The size of buffer in bytes for buffered reader of dal. By default, it is 1MB. UInt64 +timezone UTC UTC SESSION Timezone, default value: UTC, String +wait_for_async_insert 1 1 SESSION Whether the client wait for the reply of async insert, default value: 1 UInt64 +wait_for_async_insert_timeout 100 100 SESSION The timeout in seconds for waiting for processing of async insert, default value: 100 UInt64 +enable_async_insert 0 0 SESSION Whether the client open async insert mode, default value: 0 UInt64 +enable_new_processor_framework 1 1 SESSION Enable new processor framework if value != 0, default value: 1 UInt64 +enable_planner_v2 1 0 SESSION Enable planner v2 by setting this variable to 1, default value: 0 UInt64 diff --git a/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.sql b/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.sql new file mode 100644 index 000000000000..a58f6ec0ba6e --- /dev/null +++ b/tests/suites/0_stateless/06_show/06_0003_show_settings_v2.sql @@ -0,0 +1,6 @@ +SET enable_planner_v2=1; +SET max_threads=11; +SET unknown_settings=11; -- {ErrorCode 2801} +SHOW SETTINGS; +SHOW SETTINGS LIKE 'enable%'; +SET enable_planner_v2=0;