From 0dc83f69b5b47699181666691e72d83d7bc80331 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Thu, 2 Jul 2026 12:03:49 +0800 Subject: [PATCH] fix(agent): execute transaction control SQL as statements --- .../main/java/com/dbx/agent/JdbcExecutor.java | 36 ++---------------- .../com/dbx/agent/AbstractJdbcAgentTest.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/agents/common/src/main/java/com/dbx/agent/JdbcExecutor.java b/agents/common/src/main/java/com/dbx/agent/JdbcExecutor.java index 5c911cd95e..0da63753db 100644 --- a/agents/common/src/main/java/com/dbx/agent/JdbcExecutor.java +++ b/agents/common/src/main/java/com/dbx/agent/JdbcExecutor.java @@ -67,24 +67,8 @@ public final class JdbcExecutor { ) { return unchecked(() -> { String trimmedSql = trimSql(sql); - String upperSql = trimmedSql.toUpperCase(Locale.ROOT).trim(); long start = System.currentTimeMillis(); - if ("BEGIN".equals(upperSql) || "BEGIN TRANSACTION".equals(upperSql)) { - conn.setAutoCommit(false); - return emptyQueryResult(start); - } - if ("COMMIT".equals(upperSql)) { - conn.commit(); - conn.setAutoCommit(true); - return emptyQueryResult(start); - } - if ("ROLLBACK".equals(upperSql)) { - conn.rollback(); - conn.setAutoCommit(true); - return emptyQueryResult(start); - } - applySchema(conn, schema, setSchemaSql); try (Statement stmt = conn.createStatement()) { @@ -94,6 +78,8 @@ public final class JdbcExecutor { if (fetchSize != null && fetchSize > 0) { stmt.setFetchSize(fetchSize); } + // SQL dumps often contain BEGIN/COMMIT/ROLLBACK as executable statements. + // Do not translate them to Connection.commit(), which requires autoCommit=false. boolean hasResultSet = stmt.execute(trimmedSql); long elapsed = System.currentTimeMillis() - start; if (hasResultSet) { @@ -204,24 +190,8 @@ public final class JdbcExecutor { return unchecked(() -> { expireIdleSessions(targetSessions, System.currentTimeMillis(), QUERY_SESSION_IDLE_TIMEOUT_MILLIS); String trimmedSql = trimSql(sql); - String upperSql = trimmedSql.toUpperCase(Locale.ROOT).trim(); long start = System.currentTimeMillis(); - if ("BEGIN".equals(upperSql) || "BEGIN TRANSACTION".equals(upperSql)) { - conn.setAutoCommit(false); - return emptyQueryPageResult(start); - } - if ("COMMIT".equals(upperSql)) { - conn.commit(); - conn.setAutoCommit(true); - return emptyQueryPageResult(start); - } - if ("ROLLBACK".equals(upperSql)) { - conn.rollback(); - conn.setAutoCommit(true); - return emptyQueryPageResult(start); - } - applySchema(conn, schema, setSchemaSql); Statement stmt = conn.createStatement(); @@ -230,6 +200,8 @@ public final class JdbcExecutor { if (options.getFetchSize() != null && options.getFetchSize() > 0) { stmt.setFetchSize(options.getFetchSize()); } + // Keep script transaction-control statements in the SQL stream. + // JDBC transaction APIs are reserved for executeTransaction. boolean hasResultSet = stmt.execute(trimmedSql); long elapsed = System.currentTimeMillis() - start; if (!hasResultSet) { diff --git a/agents/common/src/test/java/com/dbx/agent/AbstractJdbcAgentTest.java b/agents/common/src/test/java/com/dbx/agent/AbstractJdbcAgentTest.java index c6fe1b5710..5c03e74644 100644 --- a/agents/common/src/test/java/com/dbx/agent/AbstractJdbcAgentTest.java +++ b/agents/common/src/test/java/com/dbx/agent/AbstractJdbcAgentTest.java @@ -103,6 +103,44 @@ class AbstractJdbcAgentTest { assertEquals(Arrays.asList("setMaxRows:10001", "execute:BEGIN\n NULL;\nEND;"), tracking.calls); } + @Test + void executesTransactionControlSqlThroughStatements() { + TrackingConnection tracking = new TrackingConnection(); + TestAgent agent = new TestAgent(tracking); + agent.connect(new ConnectParams()); + + // Dump files can contain explicit transaction SQL while the JDBC connection is in auto-commit mode. + agent.executeQuery("BEGIN;", null, new ExecuteQueryOptions()); + agent.executeQuery("BEGIN TRANSACTION;", null, new ExecuteQueryOptions()); + agent.executeQuery("COMMIT;", null, new ExecuteQueryOptions()); + agent.executeQuery("ROLLBACK;", null, new ExecuteQueryOptions()); + + assertEquals( + Arrays.asList( + "setMaxRows:10001", + "execute:BEGIN", + "setMaxRows:10001", + "execute:BEGIN TRANSACTION", + "setMaxRows:10001", + "execute:COMMIT", + "setMaxRows:10001", + "execute:ROLLBACK" + ), + tracking.calls + ); + } + + @Test + void executesPagedTransactionControlSqlThroughStatements() { + TrackingConnection tracking = new TrackingConnection(); + TestAgent agent = new TestAgent(tracking); + agent.connect(new ConnectParams()); + + agent.executeQueryPage("COMMIT;", null, new QueryPageOptions()); + + assertEquals(Collections.singletonList("execute:COMMIT"), tracking.calls); + } + @Test void delegatesTransactionsThroughSharedFoundation() { TrackingConnection tracking = new TrackingConnection();