diff --git a/Cargo.lock b/Cargo.lock index 39055a614defb..4d7b6580e87b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4286,6 +4286,7 @@ name = "databend-common-tracing" version = "0.1.0" dependencies = [ "databend-common-base", + "databend-common-exception", "defer", "fern", "humantime", diff --git a/src/common/exception/src/exception_backtrace.rs b/src/common/exception/src/exception_backtrace.rs index 2ac1c949d4c43..ef50db7f0c350 100644 --- a/src/common/exception/src/exception_backtrace.rs +++ b/src/common/exception/src/exception_backtrace.rs @@ -19,9 +19,19 @@ use std::sync::Arc; use crate::exception::ErrorCodeBacktrace; +// 0: not specified 1: disable 2: enable +pub static USER_SET_ENABLE_BACKTRACE: AtomicUsize = AtomicUsize::new(0); + +pub fn set_backtrace(switch: bool) { + if switch { + USER_SET_ENABLE_BACKTRACE.store(2, Ordering::Relaxed); + } else { + USER_SET_ENABLE_BACKTRACE.store(1, Ordering::Relaxed); + } +} + fn enable_rust_backtrace() -> bool { - static ENABLED: AtomicUsize = AtomicUsize::new(0); - match ENABLED.load(Ordering::Relaxed) { + match USER_SET_ENABLE_BACKTRACE.load(Ordering::Relaxed) { 0 => {} 1 => return false, _ => return true, @@ -35,7 +45,7 @@ fn enable_rust_backtrace() -> bool { }, }; - ENABLED.store(enabled as usize + 1, Ordering::Relaxed); + USER_SET_ENABLE_BACKTRACE.store(enabled as usize + 1, Ordering::Relaxed); enabled } diff --git a/src/common/exception/src/lib.rs b/src/common/exception/src/lib.rs index 9aa1d8c9733d7..3e9be10a24154 100644 --- a/src/common/exception/src/lib.rs +++ b/src/common/exception/src/lib.rs @@ -23,6 +23,8 @@ mod with_context; pub use exception::ErrorCode; pub use exception::Result; pub use exception::ToErrorCode; +pub use exception_backtrace::set_backtrace; +pub use exception_backtrace::USER_SET_ENABLE_BACKTRACE; pub use exception_into::SerializedError; pub use with_context::ErrorWithContext; pub use with_context::WithContext; diff --git a/src/common/tracing/Cargo.toml b/src/common/tracing/Cargo.toml index 5a26b62544d7a..953277848d259 100644 --- a/src/common/tracing/Cargo.toml +++ b/src/common/tracing/Cargo.toml @@ -12,6 +12,7 @@ test = true [dependencies] databend-common-base = { workspace = true } +databend-common-exception = { workspace = true } defer = "0.2" fern = "0.6.2" humantime = "2.1.0" diff --git a/src/common/tracing/src/panic_hook.rs b/src/common/tracing/src/panic_hook.rs index bbb54d6bd1920..844fb4e75d5d1 100644 --- a/src/common/tracing/src/panic_hook.rs +++ b/src/common/tracing/src/panic_hook.rs @@ -14,8 +14,10 @@ use std::backtrace::Backtrace; use std::panic::PanicInfo; +use std::sync::atomic::Ordering; use databend_common_base::runtime::LimitMemGuard; +use databend_common_exception::USER_SET_ENABLE_BACKTRACE; use log::error; pub fn set_panic_hook() { @@ -31,12 +33,25 @@ pub fn set_panic_hook() { })); } +fn should_backtrace() -> bool { + // if user not specify or user set to enable, we should backtrace + match USER_SET_ENABLE_BACKTRACE.load(Ordering::Relaxed) { + 0 => true, + 1 => false, + _ => true, + } +} + pub fn log_panic(panic: &PanicInfo) { - let backtrace = Backtrace::force_capture(); - let backtrace_str = format!("{:?}", backtrace); + let backtrace_str = if should_backtrace() { + let backtrace = Backtrace::force_capture(); + format!("{:?}", backtrace) + } else { + String::new() + }; eprintln!("{}", panic); - eprintln!("{}", backtrace); + eprintln!("{}", backtrace_str); if let Some(location) = panic.location() { error!( diff --git a/src/query/ast/src/ast/statements/mod.rs b/src/query/ast/src/ast/statements/mod.rs index b1e7c8ae756a1..9ccc60c52afe2 100644 --- a/src/query/ast/src/ast/statements/mod.rs +++ b/src/query/ast/src/ast/statements/mod.rs @@ -45,6 +45,7 @@ mod show; mod stage; mod statement; mod stream; +mod system_action; mod table; mod task; mod udf; @@ -87,6 +88,7 @@ pub use show::*; pub use stage::*; pub use statement::*; pub use stream::*; +pub use system_action::*; pub use table::*; pub use task::*; pub use udf::*; diff --git a/src/query/ast/src/ast/statements/statement.rs b/src/query/ast/src/ast/statements/statement.rs index 6f5e688879706..963e8200f2f48 100644 --- a/src/query/ast/src/ast/statements/statement.rs +++ b/src/query/ast/src/ast/statements/statement.rs @@ -317,6 +317,9 @@ pub enum Statement { priority: Priority, object_id: String, }, + + // System actions + System(SystemStmt), } impl Statement { @@ -721,6 +724,7 @@ impl Display for Statement { write!(f, " {priority}")?; write!(f, " '{object_id}'")?; } + Statement::System(stmt) => write!(f, "{stmt}")?, } Ok(()) } diff --git a/src/query/ast/src/ast/statements/system_action.rs b/src/query/ast/src/ast/statements/system_action.rs new file mode 100644 index 0000000000000..fbe3a89759f5e --- /dev/null +++ b/src/query/ast/src/ast/statements/system_action.rs @@ -0,0 +1,46 @@ +// 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; + +#[derive(Debug, Clone, PartialEq, Drive, DriveMut)] +pub struct SystemStmt { + pub action: SystemAction, +} + +impl Display for SystemStmt { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + write!(f, "SYSTEM {}", self.action) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] +pub enum SystemAction { + Backtrace(bool), +} + +impl Display for SystemAction { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + match self { + SystemAction::Backtrace(switch) => match switch { + true => write!(f, "ENABLE EXCEPTION_BACKTRACE"), + false => write!(f, "DISABLE EXCEPTION_BACKTRACE"), + }, + } + } +} diff --git a/src/query/ast/src/ast/visitors/visitor.rs b/src/query/ast/src/ast/visitors/visitor.rs index 59ea6a6aeed29..a8d925cc1c1af 100644 --- a/src/query/ast/src/ast/visitors/visitor.rs +++ b/src/query/ast/src/ast/visitors/visitor.rs @@ -844,4 +844,6 @@ pub trait Visitor<'ast>: Sized { fn visit_drop_sequence(&mut self, _stmt: &'ast DropSequenceStmt) {} fn visit_set_priority(&mut self, _priority: &'ast Priority, _object_id: &'ast str) {} fn visit_multi_table_insert(&mut self, insert: &'ast InsertMultiTableStmt); + + fn visit_system(&mut self, _stmt: &'ast SystemStmt) {} } diff --git a/src/query/ast/src/ast/visitors/visitor_mut.rs b/src/query/ast/src/ast/visitors/visitor_mut.rs index 738fd76d884b9..5a3b4c11776e0 100644 --- a/src/query/ast/src/ast/visitors/visitor_mut.rs +++ b/src/query/ast/src/ast/visitors/visitor_mut.rs @@ -854,4 +854,5 @@ pub trait VisitorMut: Sized { fn visit_create_sequence(&mut self, _stmt: &mut CreateSequenceStmt) {} fn visit_drop_sequence(&mut self, _stmt: &mut DropSequenceStmt) {} fn visit_set_priority(&mut self, _priority: &mut Priority, _object_id: &mut String) {} + fn visit_system(&mut self, _stmt: &mut SystemStmt) {} } diff --git a/src/query/ast/src/ast/visitors/walk.rs b/src/query/ast/src/ast/visitors/walk.rs index 663cbeebc91de..f71f26dae482e 100644 --- a/src/query/ast/src/ast/visitors/walk.rs +++ b/src/query/ast/src/ast/visitors/walk.rs @@ -597,5 +597,6 @@ pub fn walk_statement<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Statem priority, object_id, } => visitor.visit_set_priority(priority, object_id), + Statement::System(stmt) => visitor.visit_system(stmt), } } diff --git a/src/query/ast/src/ast/visitors/walk_mut.rs b/src/query/ast/src/ast/visitors/walk_mut.rs index baae6a066906f..e209d633e45fa 100644 --- a/src/query/ast/src/ast/visitors/walk_mut.rs +++ b/src/query/ast/src/ast/visitors/walk_mut.rs @@ -596,5 +596,6 @@ pub fn walk_statement_mut(visitor: &mut V, statement: &mut Statem priority, object_id, } => visitor.visit_set_priority(priority, object_id), + Statement::System(stmt) => visitor.visit_system(stmt), } } diff --git a/src/query/ast/src/parser/statement.rs b/src/query/ast/src/parser/statement.rs index 84d31959fb20b..76518d4dfad0f 100644 --- a/src/query/ast/src/parser/statement.rs +++ b/src/query/ast/src/parser/statement.rs @@ -2047,6 +2047,13 @@ pub fn statement_body(i: Input) -> IResult { |(_, _, script)| Statement::ExecuteImmediate(ExecuteImmediateStmt { script }), ); + let system_action = map( + rule! { + SYSTEM ~ #action + }, + |(_, action)| Statement::System(SystemStmt { action }), + ); + alt(( // query, explain,show rule!( @@ -2063,7 +2070,8 @@ pub fn statement_body(i: Input) -> IResult { | #show_locks : "`SHOW LOCKS [IN ACCOUNT] [WHERE ...]`" | #kill_stmt : "`KILL (QUERY | CONNECTION) `" | #vacuum_temp_files : "VACUUM TEMPORARY FILES [RETAIN number SECONDS|DAYS] [LIMIT number]" - | #set_priority: "SET PRIORITY (HIGH | MEDIUM | LOW) " + | #set_priority: "`SET PRIORITY (HIGH | MEDIUM | LOW) `" + | #system_action: "`SYSTEM (ENABLE | DISABLE) EXCEPTION_BACKTRACE`" ), // database rule!( @@ -3744,6 +3752,26 @@ pub fn priority(i: Input) -> IResult { ))(i) } +pub fn action(i: Input) -> IResult { + let mut backtrace = map( + rule! { + #switch ~ EXCEPTION_BACKTRACE + }, + |(switch, _)| SystemAction::Backtrace(switch), + ); + // add other system action type here + rule!( + #backtrace + )(i) +} + +pub fn switch(i: Input) -> IResult { + alt(( + value(true, rule! { ENABLE }), + value(false, rule! { DISABLE }), + ))(i) +} + pub fn limit_where(i: Input) -> IResult { map( rule! { diff --git a/src/query/ast/src/parser/token.rs b/src/query/ast/src/parser/token.rs index 49954fc7809aa..6939b54d244b5 100644 --- a/src/query/ast/src/parser/token.rs +++ b/src/query/ast/src/parser/token.rs @@ -502,6 +502,8 @@ pub enum TokenKind { DETAILED_OUTPUT, #[token("DESCRIBE", ignore(ascii_case))] DESCRIBE, + #[token("DISABLE", ignore(ascii_case))] + DISABLE, #[token("DISABLE_VARIANT_CHECK", ignore(ascii_case))] DISABLE_VARIANT_CHECK, #[token("DISTINCT", ignore(ascii_case))] @@ -540,6 +542,8 @@ pub enum TokenKind { ELSE, #[token("EMPTY_FIELD_AS", ignore(ascii_case))] EMPTY_FIELD_AS, + #[token("ENABLE", ignore(ascii_case))] + ENABLE, #[token("ENABLE_VIRTUAL_HOST_STYLE", ignore(ascii_case))] ENABLE_VIRTUAL_HOST_STYLE, #[token("END", ignore(ascii_case))] @@ -556,6 +560,8 @@ pub enum TokenKind { ERROR_ON_COLUMN_COUNT_MISMATCH, #[token("ESCAPE", ignore(ascii_case))] ESCAPE, + #[token("EXCEPTION_BACKTRACE", ignore(ascii_case))] + EXCEPTION_BACKTRACE, #[token("EXISTS", ignore(ascii_case))] EXISTS, #[token("EXPLAIN", ignore(ascii_case))] @@ -1055,6 +1061,8 @@ pub enum TokenKind { SOUNDS, #[token("SYNC", ignore(ascii_case))] SYNC, + #[token("SYSTEM", ignore(ascii_case))] + SYSTEM, #[token("STORAGE_TYPE", ignore(ascii_case))] STORAGE_TYPE, #[token("TABLE", ignore(ascii_case))] diff --git a/src/query/service/src/interpreters/access/privilege_access.rs b/src/query/service/src/interpreters/access/privilege_access.rs index 9263743ecb074..f6f8b66b849e9 100644 --- a/src/query/service/src/interpreters/access/privilege_access.rs +++ b/src/query/service/src/interpreters/access/privilege_access.rs @@ -1069,7 +1069,7 @@ impl AccessChecker for PrivilegeAccess { self.validate_access(&GrantObject::Global, UserPrivilegeType::Grant,false) .await?; } - Plan::SetVariable(_) | Plan::UnSetVariable(_) | Plan::Kill(_) | Plan::SetPriority(_) => { + Plan::SetVariable(_) | Plan::UnSetVariable(_) | Plan::Kill(_) | Plan::SetPriority(_) | Plan::System(_) => { self.validate_access(&GrantObject::Global, UserPrivilegeType::Super, false) .await?; } diff --git a/src/query/service/src/interpreters/interpreter_factory.rs b/src/query/service/src/interpreters/interpreter_factory.rs index 3cb94513e079d..483cc04f00e58 100644 --- a/src/query/service/src/interpreters/interpreter_factory.rs +++ b/src/query/service/src/interpreters/interpreter_factory.rs @@ -50,6 +50,7 @@ use crate::interpreters::interpreter_notification_drop::DropNotificationInterpre use crate::interpreters::interpreter_presign::PresignInterpreter; use crate::interpreters::interpreter_role_show::ShowRolesInterpreter; use crate::interpreters::interpreter_set_priority::SetPriorityInterpreter; +use crate::interpreters::interpreter_system_action::SystemActionInterpreter; use crate::interpreters::interpreter_table_create::CreateTableInterpreter; use crate::interpreters::interpreter_table_revert::RevertTableInterpreter; use crate::interpreters::interpreter_task_alter::AlterTaskInterpreter; @@ -598,6 +599,10 @@ impl InterpreterFactory { ctx, *p.clone(), )?)), + Plan::System(p) => Ok(Arc::new(SystemActionInterpreter::try_create( + ctx, + *p.clone(), + )?)), } } } diff --git a/src/query/service/src/interpreters/interpreter_system_action.rs b/src/query/service/src/interpreters/interpreter_system_action.rs new file mode 100644 index 0000000000000..5233fb8d8e3e9 --- /dev/null +++ b/src/query/service/src/interpreters/interpreter_system_action.rs @@ -0,0 +1,89 @@ +// 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::sync::Arc; + +use databend_common_catalog::table_context::TableContext; +use databend_common_config::GlobalConfig; +use databend_common_exception::set_backtrace; +use databend_common_exception::Result; +use databend_common_sql::plans::SystemAction; +use databend_common_sql::plans::SystemPlan; + +use crate::interpreters::Interpreter; +use crate::pipelines::PipelineBuildResult; +use crate::servers::flight::v1::packets::Packet; +use crate::servers::flight::v1::packets::SystemActionPacket; +use crate::sessions::QueryContext; + +pub struct SystemActionInterpreter { + ctx: Arc, + plan: SystemPlan, + proxy_to_cluster: bool, +} + +impl SystemActionInterpreter { + pub fn try_create(ctx: Arc, plan: SystemPlan) -> Result { + Ok(SystemActionInterpreter { + ctx, + plan, + proxy_to_cluster: true, + }) + } + + pub fn from_flight(ctx: Arc, packet: SystemActionPacket) -> Result { + Ok(SystemActionInterpreter { + ctx, + plan: SystemPlan { + action: packet.action, + }, + proxy_to_cluster: false, + }) + } +} + +#[async_trait::async_trait] +impl Interpreter for SystemActionInterpreter { + fn name(&self) -> &str { + "SystemActionInterpreter" + } + + fn is_ddl(&self) -> bool { + false + } + + #[async_backtrace::framed] + #[minitrace::trace] + async fn execute2(&self) -> Result { + if self.proxy_to_cluster { + let settings = self.ctx.get_settings(); + let timeout = settings.get_flight_client_timeout()?; + let conf = GlobalConfig::instance(); + let cluster = self.ctx.get_cluster(); + for node_info in &cluster.nodes { + if node_info.id != cluster.local_id { + let system_action_packet = + SystemActionPacket::create(self.plan.action.clone(), node_info.clone()); + system_action_packet.commit(conf.as_ref(), timeout).await?; + } + } + } + match self.plan.action { + SystemAction::Backtrace(switch) => { + set_backtrace(switch); + } + } + Ok(PipelineBuildResult::create()) + } +} diff --git a/src/query/service/src/interpreters/mod.rs b/src/query/service/src/interpreters/mod.rs index b3f4d58477f15..d51afb68d0c73 100644 --- a/src/query/service/src/interpreters/mod.rs +++ b/src/query/service/src/interpreters/mod.rs @@ -94,6 +94,7 @@ mod interpreter_share_show_grant_tenants; mod interpreter_show_object_grant_privileges; mod interpreter_stream_create; mod interpreter_stream_drop; +mod interpreter_system_action; mod interpreter_table_add_column; mod interpreter_table_analyze; mod interpreter_table_create; @@ -211,6 +212,7 @@ pub use interpreter_share_show_grant_tenants::ShowGrantTenantsOfShareInterpreter pub use interpreter_show_object_grant_privileges::ShowObjectGrantPrivilegesInterpreter; pub use interpreter_stream_create::CreateStreamInterpreter; pub use interpreter_stream_drop::DropStreamInterpreter; +pub use interpreter_system_action::SystemActionInterpreter; pub use interpreter_table_add_column::AddTableColumnInterpreter; pub use interpreter_table_analyze::AnalyzeTableInterpreter; pub use interpreter_table_create::CreateTableInterpreter; diff --git a/src/query/service/src/servers/flight/v1/actions/flight_actions.rs b/src/query/service/src/servers/flight/v1/actions/flight_actions.rs index d3c28bb580bf5..e20476ee9136b 100644 --- a/src/query/service/src/servers/flight/v1/actions/flight_actions.rs +++ b/src/query/service/src/servers/flight/v1/actions/flight_actions.rs @@ -31,11 +31,13 @@ use crate::servers::flight::v1::actions::kill_query::kill_query; use crate::servers::flight::v1::actions::set_priority::set_priority; use crate::servers::flight::v1::actions::set_priority::SET_PRIORITY; use crate::servers::flight::v1::actions::start_prepared_query::start_prepared_query; +use crate::servers::flight::v1::actions::system_action::system_action; use crate::servers::flight::v1::actions::truncate_table::truncate_table; use crate::servers::flight::v1::actions::truncate_table::TRUNCATE_TABLE; use crate::servers::flight::v1::actions::INIT_QUERY_FRAGMENTS; use crate::servers::flight::v1::actions::KILL_QUERY; use crate::servers::flight::v1::actions::START_PREPARED_QUERY; +use crate::servers::flight::v1::actions::SYSTEM_ACTION; pub struct FlightActions { #[allow(clippy::type_complexity)] @@ -124,4 +126,5 @@ pub fn flight_actions() -> FlightActions { .action(TRUNCATE_TABLE, truncate_table) .action(KILL_QUERY, kill_query) .action(SET_PRIORITY, set_priority) + .action(SYSTEM_ACTION, system_action) } diff --git a/src/query/service/src/servers/flight/v1/actions/mod.rs b/src/query/service/src/servers/flight/v1/actions/mod.rs index bdb007d992720..d508b15f99b9b 100644 --- a/src/query/service/src/servers/flight/v1/actions/mod.rs +++ b/src/query/service/src/servers/flight/v1/actions/mod.rs @@ -18,6 +18,7 @@ mod init_query_fragments; mod kill_query; mod set_priority; mod start_prepared_query; +mod system_action; mod truncate_table; pub use flight_actions::flight_actions; @@ -28,4 +29,5 @@ pub use init_query_fragments::INIT_QUERY_FRAGMENTS; pub use kill_query::KILL_QUERY; pub use set_priority::SET_PRIORITY; pub use start_prepared_query::START_PREPARED_QUERY; +pub use system_action::SYSTEM_ACTION; pub use truncate_table::TRUNCATE_TABLE; diff --git a/src/query/service/src/servers/flight/v1/actions/system_action.rs b/src/query/service/src/servers/flight/v1/actions/system_action.rs new file mode 100644 index 0000000000000..bb50bfb3ad48a --- /dev/null +++ b/src/query/service/src/servers/flight/v1/actions/system_action.rs @@ -0,0 +1,37 @@ +// 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 databend_common_config::GlobalConfig; +use databend_common_exception::Result; +use databend_common_settings::Settings; + +use crate::interpreters::Interpreter; +use crate::interpreters::SystemActionInterpreter; +use crate::servers::flight::v1::packets::SystemActionPacket; +use crate::sessions::SessionManager; +use crate::sessions::SessionType; + +pub static SYSTEM_ACTION: &str = "/actions/system_action"; + +pub async fn system_action(req: SystemActionPacket) -> Result<()> { + let config = GlobalConfig::instance(); + let session_manager = SessionManager::instance(); + let settings = Settings::create(config.query.tenant_id.clone()); + let session = session_manager.create_with_settings(SessionType::FlightRPC, settings)?; + let session = session_manager.register_session(session)?; + let ctx = session.create_query_context().await?; + let interpreter = SystemActionInterpreter::from_flight(ctx, req)?; + interpreter.execute2().await?; + Ok(()) +} diff --git a/src/query/service/src/servers/flight/v1/packets/mod.rs b/src/query/service/src/servers/flight/v1/packets/mod.rs index b4180c54d4b2b..8ac4639e5ad60 100644 --- a/src/query/service/src/servers/flight/v1/packets/mod.rs +++ b/src/query/service/src/servers/flight/v1/packets/mod.rs @@ -21,6 +21,7 @@ mod packet_fragment; mod packet_kill_query; mod packet_publisher; mod packet_set_priority; +mod packet_system_action; mod packet_truncate_table; pub use packet::Packet; @@ -36,4 +37,5 @@ pub use packet_publisher::DataflowDiagramBuilder; pub use packet_publisher::Edge; pub use packet_publisher::QueryEnv; pub use packet_set_priority::SetPriorityPacket; +pub use packet_system_action::SystemActionPacket; pub use packet_truncate_table::TruncateTablePacket; diff --git a/src/query/service/src/servers/flight/v1/packets/packet_system_action.rs b/src/query/service/src/servers/flight/v1/packets/packet_system_action.rs new file mode 100644 index 0000000000000..9cd4e209dcb17 --- /dev/null +++ b/src/query/service/src/servers/flight/v1/packets/packet_system_action.rs @@ -0,0 +1,49 @@ +// 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::sync::Arc; + +use databend_common_config::InnerConfig; +use databend_common_exception::Result; +use databend_common_meta_types::NodeInfo; +use databend_common_sql::plans::SystemAction; +use serde::Deserialize; +use serde::Serialize; + +use crate::servers::flight::v1::actions::SYSTEM_ACTION; +use crate::servers::flight::v1::packets::packet::create_client; +use crate::servers::flight::v1::packets::Packet; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct SystemActionPacket { + pub action: SystemAction, + pub executor: Arc, +} + +impl SystemActionPacket { + pub fn create(action: SystemAction, executor: Arc) -> Self { + SystemActionPacket { action, executor } + } +} + +#[async_trait::async_trait] +impl Packet for SystemActionPacket { + #[async_backtrace::framed] + async fn commit(&self, config: &InnerConfig, timeout: u64) -> Result<()> { + let executor_info = &self.executor; + let mut conn = create_client(config, &executor_info.flight_address).await?; + + conn.do_action(SYSTEM_ACTION, self.clone(), timeout).await + } +} diff --git a/src/query/sql/src/planner/binder/binder.rs b/src/query/sql/src/planner/binder/binder.rs index d9d7acf5e8640..8a4fa5ad2a842 100644 --- a/src/query/sql/src/planner/binder/binder.rs +++ b/src/query/sql/src/planner/binder/binder.rs @@ -618,6 +618,7 @@ impl<'a> Binder { Statement::SetPriority {priority, object_id} => { self.bind_set_priority(priority, object_id).await? }, + Statement::System(stmt) => self.bind_system(stmt).await?, }; match plan.kind() { diff --git a/src/query/sql/src/planner/binder/mod.rs b/src/query/sql/src/planner/binder/mod.rs index 7a5c2821842b5..856f85f44990b 100644 --- a/src/query/sql/src/planner/binder/mod.rs +++ b/src/query/sql/src/planner/binder/mod.rs @@ -49,6 +49,7 @@ mod show; mod sort; mod stage; mod stream_column_factory; +mod system; mod table; mod table_args; mod udf; diff --git a/src/query/sql/src/planner/binder/system.rs b/src/query/sql/src/planner/binder/system.rs new file mode 100644 index 0000000000000..d811441bde23e --- /dev/null +++ b/src/query/sql/src/planner/binder/system.rs @@ -0,0 +1,34 @@ +// 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 databend_common_ast::ast::SystemAction as AstSystemAction; +use databend_common_ast::ast::SystemStmt; +use databend_common_exception::Result; + +use crate::planner::binder::Binder; +use crate::plans::Plan; +use crate::plans::SystemAction; +use crate::plans::SystemPlan; + +impl Binder { + #[async_backtrace::framed] + pub(super) async fn bind_system(&mut self, stmt: &SystemStmt) -> Result { + let SystemStmt { action } = stmt; + match action { + AstSystemAction::Backtrace(switch) => Ok(Plan::System(Box::new(SystemPlan { + action: SystemAction::Backtrace(*switch), + }))), + } + } +} diff --git a/src/query/sql/src/planner/format/display_plan.rs b/src/query/sql/src/planner/format/display_plan.rs index 129de43e4c4b4..5e7e7a9335ae0 100644 --- a/src/query/sql/src/planner/format/display_plan.rs +++ b/src/query/sql/src/planner/format/display_plan.rs @@ -226,6 +226,7 @@ impl Plan { Plan::DropSequence(_) => Ok("DropSequence".to_string()), Plan::SetPriority(_) => Ok("SetPriority".to_string()), + Plan::System(_) => Ok("System".to_string()), } } } diff --git a/src/query/sql/src/planner/plans/mod.rs b/src/query/sql/src/planner/plans/mod.rs index 75742479a2c17..2554cf93c7d87 100644 --- a/src/query/sql/src/planner/plans/mod.rs +++ b/src/query/sql/src/planner/plans/mod.rs @@ -52,6 +52,7 @@ mod set_priority; mod setting; pub mod share; mod sort; +mod system; mod union_all; mod update; mod window; @@ -101,6 +102,7 @@ pub use set_priority::SetPriorityPlan; pub use setting::*; pub use share::*; pub use sort::*; +pub use system::*; pub use udf::*; pub use union_all::UnionAll; pub use update::*; diff --git a/src/query/sql/src/planner/plans/plan.rs b/src/query/sql/src/planner/plans/plan.rs index 81042a017313f..c07d9dba56957 100644 --- a/src/query/sql/src/planner/plans/plan.rs +++ b/src/query/sql/src/planner/plans/plan.rs @@ -144,6 +144,7 @@ use crate::plans::ShowRolesPlan; use crate::plans::ShowShareEndpointPlan; use crate::plans::ShowSharesPlan; use crate::plans::ShowTasksPlan; +use crate::plans::SystemPlan; use crate::plans::TruncateTablePlan; use crate::plans::UnSettingPlan; use crate::plans::UndropDatabasePlan; @@ -305,6 +306,7 @@ pub enum Plan { UnSetVariable(Box), Kill(Box), SetPriority(Box), + System(Box), // Share CreateShareEndpoint(Box), diff --git a/src/query/sql/src/planner/plans/system.rs b/src/query/sql/src/planner/plans/system.rs new file mode 100644 index 0000000000000..0187548609fe4 --- /dev/null +++ b/src/query/sql/src/planner/plans/system.rs @@ -0,0 +1,26 @@ +// 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 serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SystemPlan { + pub action: SystemAction, +} + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub enum SystemAction { + Backtrace(bool), +} diff --git a/tests/sqllogictests/suites/base/20+_others/20_0017_system_action.test b/tests/sqllogictests/suites/base/20+_others/20_0017_system_action.test new file mode 100644 index 0000000000000..b0fea51f0ae2a --- /dev/null +++ b/tests/sqllogictests/suites/base/20+_others/20_0017_system_action.test @@ -0,0 +1,5 @@ +statement ok +SYSTEM ENABLE EXCEPTION_BACKTRACE; + +statement ok +SYSTEM DISABLE EXCEPTION_BACKTRACE;