From d14fd84709a2bc43afecd4d1480cac470970c24d Mon Sep 17 00:00:00 2001 From: zipg Date: Sun, 19 Jul 2026 08:53:20 +0800 Subject: [PATCH] fix(mysql): preserve results after hash comments --- crates/dbx-core/src/db/mysql.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/crates/dbx-core/src/db/mysql.rs b/crates/dbx-core/src/db/mysql.rs index bf28d3441c..5f41f7929b 100644 --- a/crates/dbx-core/src/db/mysql.rs +++ b/crates/dbx-core/src/db/mysql.rs @@ -13,7 +13,7 @@ use std::time::Instant; use tokio_util::sync::CancellationToken; use crate::models::connection::{ConnectionConfig, DatabaseConnectionInfo, DatabaseType}; -use crate::sql::starts_with_executable_sql_keyword; +use crate::sql::{starts_with_executable_sql_keyword, starts_with_executable_sql_keyword_for_database}; use crate::types::{ ColumnInfo, CompletionAssistantCandidate, CompletionAssistantCandidateKind, CompletionAssistantMatchMode, CompletionAssistantObjectKind, CompletionAssistantRequest, CompletionAssistantResponse, DatabaseInfo, @@ -3198,8 +3198,11 @@ fn prefers_text_protocol_query(sql: &str, dialect: MySqlQueryDialect) -> bool { } fn is_result_set_query(sql: &str, dialect: MySqlQueryDialect) -> bool { - starts_with_executable_sql_keyword(sql, &["SELECT", "SHOW", "DESCRIBE", "EXPLAIN", "WITH", "CALL"]) - || dialect.supports_admin_show_results && is_admin_show_query(sql) + starts_with_executable_sql_keyword_for_database( + sql, + &["SELECT", "SHOW", "DESCRIBE", "EXPLAIN", "WITH", "CALL"], + DatabaseType::Mysql, + ) || dialect.supports_admin_show_results && is_admin_show_query(sql) } fn requires_text_protocol_query(sql: &str, dialect: MySqlQueryDialect) -> bool { @@ -3207,12 +3210,11 @@ fn requires_text_protocol_query(sql: &str, dialect: MySqlQueryDialect) -> bool { return true; } - if !starts_with_executable_sql_keyword(sql, &["SHOW"]) { + if !starts_with_executable_sql_keyword_for_database(sql, &["SHOW"], DatabaseType::Mysql) { return false; } - let tokens = - sql.trim().trim_end_matches(';').split_whitespace().map(|token| token.to_ascii_lowercase()).collect::>(); + let tokens = leading_sql_word_tokens(sql, 3); if tokens.len() >= 2 && tokens[0] == "show" && tokens[1] == "grants" { return true; } @@ -3987,6 +3989,16 @@ mod tests { assert!(is_result_set_query(sql, MySqlQueryDialect::default())); } + #[test] + fn mysql_hash_comments_before_queries_preserve_result_sets_per_issue_3830() { + let dialect = MySqlQueryDialect::default(); + + assert!(is_result_set_query("# 注释\nSELECT NOW()", dialect)); + assert!(prefers_text_protocol_query("# 注释\nSELECT NOW()", dialect)); + assert!(requires_text_protocol_query("# inspect sessions\nSHOW PROCESSLIST", dialect)); + assert!(!is_result_set_query("# update row\nUPDATE users SET name = 'Ada' WHERE id = 1", dialect)); + } + #[test] fn mysql_desc_queries_are_treated_as_result_sets() { assert!(is_result_set_query("DESC users", MySqlQueryDialect::default()));