fix(sqlserver): route transaction control statements through simple_query

BEGIN TRANSACTION / COMMIT / ROLLBACK must not go through sp_executesql
(client.execute) because SQL Server raises error 266 when @@TRANCOUNT
changes inside sp_executesql. Route them through simple_query instead.
This commit is contained in:
t8y2 2026-05-20 13:36:08 +08:00
parent 62af348a01
commit c53caddc3f
1 changed files with 18 additions and 1 deletions

View File

@ -554,7 +554,7 @@ pub async fn execute_query_with_max_rows(
if starts_with_executable_sql_keyword(sql, &["SELECT", "EXEC", "WITH", "TABLE"]) {
let stream = client.query(sql, &[]).await.map_err(|e| e.to_string())?;
collect_first_result_limited(stream, start, max_rows).await
} else if requires_simple_query_batch(sql) {
} else if requires_simple_query_batch(sql) || is_transaction_control(sql) {
let stream = client.simple_query(sql).await.map_err(|e| e.to_string())?;
let _ = collect_result_sets_limited(stream, start, max_rows).await?;
Ok(QueryResult {
@ -608,6 +608,23 @@ pub async fn execute_batch_with_max_rows(
Ok(results)
}
fn is_transaction_control(sql: &str) -> bool {
let tokens = first_sql_tokens(sql, 2);
if tokens.is_empty() {
return false;
}
let first = &tokens[0];
if first.eq_ignore_ascii_case("COMMIT") || first.eq_ignore_ascii_case("ROLLBACK") {
return true;
}
if first.eq_ignore_ascii_case("BEGIN") {
return tokens
.get(1)
.map_or(false, |t| t.eq_ignore_ascii_case("TRANSACTION") || t.eq_ignore_ascii_case("TRAN"));
}
false
}
fn requires_simple_query_batch(sql: &str) -> bool {
let tokens = first_sql_tokens(sql, 4);
if tokens.len() >= 4