diff --git a/src/frontend/src/instance.rs b/src/frontend/src/instance.rs index c41475c50a..8f921f1b7c 100644 --- a/src/frontend/src/instance.rs +++ b/src/frontend/src/instance.rs @@ -314,9 +314,13 @@ impl Instance { /// For MySQL, it applies only to read-only statements. fn derive_timeout(stmt: &Statement, query_ctx: &QueryContextRef) -> Option { let query_timeout = query_ctx.query_timeout()?; - match (query_ctx.channel(), stmt) { - (Channel::Mysql, Statement::Query(_)) | (Channel::Postgres, _) => Some(query_timeout), - (_, _) => None, + if query_timeout.is_zero() { + return None; + } + match query_ctx.channel() { + Channel::Mysql if stmt.is_readonly() => Some(query_timeout), + Channel::Postgres => Some(query_timeout), + _ => None, } } diff --git a/src/sql/src/statements/statement.rs b/src/sql/src/statements/statement.rs index 030a2334c1..b514845304 100644 --- a/src/sql/src/statements/statement.rs +++ b/src/sql/src/statements/statement.rs @@ -143,6 +143,67 @@ pub enum Statement { Kill(Kill), } +impl Statement { + pub fn is_readonly(&self) -> bool { + match self { + // Read-only operations + Statement::Query(_) + | Statement::ShowDatabases(_) + | Statement::ShowTables(_) + | Statement::ShowTableStatus(_) + | Statement::ShowColumns(_) + | Statement::ShowCharset(_) + | Statement::ShowCollation(_) + | Statement::ShowIndex(_) + | Statement::ShowRegion(_) + | Statement::ShowCreateDatabase(_) + | Statement::ShowCreateTable(_) + | Statement::ShowCreateFlow(_) + | Statement::ShowFlows(_) + | Statement::ShowCreateView(_) + | Statement::ShowStatus(_) + | Statement::ShowSearchPath(_) + | Statement::ShowViews(_) + | Statement::DescribeTable(_) + | Statement::Explain(_) + | Statement::ShowVariables(_) + | Statement::ShowProcesslist(_) + | Statement::FetchCursor(_) + | Statement::Tql(_) => true, + + #[cfg(feature = "enterprise")] + Statement::ShowTriggers(_) => true, + + // Write operations + Statement::Insert(_) + | Statement::Delete(_) + | Statement::CreateTable(_) + | Statement::CreateExternalTable(_) + | Statement::CreateTableLike(_) + | Statement::CreateFlow(_) + | Statement::CreateView(_) + | Statement::DropTable(_) + | Statement::DropDatabase(_) + | Statement::DropFlow(_) + | Statement::DropView(_) + | Statement::CreateDatabase(_) + | Statement::AlterTable(_) + | Statement::AlterDatabase(_) + | Statement::Copy(_) + | Statement::TruncateTable(_) + | Statement::SetVariables(_) + | Statement::Use(_) + | Statement::DeclareCursor(_) + | Statement::CloseCursor(_) + | Statement::Kill(_) + | Statement::Admin(_) => false, + + #[cfg(feature = "enterprise")] + Statement::CreateTrigger(_) | Statement::DropTrigger(_) => false, + } + } +} + impl Display for Statement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self {