From 940f14b17e6483aef8395653cdbfdf4e1bab1904 Mon Sep 17 00:00:00 2001 From: staff Date: Mon, 29 Jun 2026 15:52:46 +0800 Subject: [PATCH] fix: fallback agent batch execution errors --- crates/dbx-core/src/query.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/dbx-core/src/query.rs b/crates/dbx-core/src/query.rs index 554d0549d..bdae7d9f4 100644 --- a/crates/dbx-core/src/query.rs +++ b/crates/dbx-core/src/query.rs @@ -1861,7 +1861,7 @@ pub async fn execute_statements( match result { Ok(result) => return Ok(db::QueryResult { execution_time_ms: start.elapsed().as_millis(), ..result }), Err(err) => { - if err.contains("Unknown method: execute_batch") { + if is_agent_execute_batch_unsupported(&err) { log::warn!( "Agent does not support execute_batch; falling back to statement-by-statement execution" ); @@ -1928,6 +1928,11 @@ pub async fn execute_statements( }) } +fn is_agent_execute_batch_unsupported(error: &str) -> bool { + let lower = error.to_lowercase(); + lower.contains("execute_batch") && (lower.contains("unknown method") || lower.contains("method not found")) +} + /// Execute multiple SQL statements within a single transaction. /// For pooled drivers (Postgres/MySQL), uses the driver transaction API. /// For SQLite and already-single-connection drivers (ClickHouse/SqlServer/Agent), @@ -2404,6 +2409,19 @@ mod tests { } } + #[test] + fn agent_execute_batch_unsupported_detects_case_insensitive_method_errors() { + assert!(is_agent_execute_batch_unsupported("Agent RPC error (-1): unknown method: execute_batch")); + assert!(is_agent_execute_batch_unsupported("Agent RPC error (-1): Unknown method: execute_batch")); + assert!(is_agent_execute_batch_unsupported("Agent RPC error (-32601): Method not found: execute_batch")); + } + + #[test] + fn agent_execute_batch_unsupported_ignores_unrelated_errors() { + assert!(!is_agent_execute_batch_unsupported("ORA-00955: name is already used by an existing object")); + assert!(!is_agent_execute_batch_unsupported("Agent RPC error (-1): unknown method: execute_query")); + } + #[tokio::test] async fn wait_for_query_returns_cancelled_when_token_is_cancelled() { let token = CancellationToken::new();