fix(data-compare): batch sync execution

This commit is contained in:
t8y2 committed 2026-06-26 17:10:26 +08:00
1 parent 895f116b04
commit 2f06ca5fe3
12 files changed
+611 -63

No files matched your search

@@ -31,6 +31,7 @@ public final class AgentProtocol {
public static final String METHOD_FETCH_TABLE_READ_PAGE = "fetch_table_read_page";
public static final String METHOD_CLOSE_TABLE_READ_SESSION = "close_table_read_session";
public static final String METHOD_GET_EXPLAIN_INFO = "get_explain_info";
public static final String METHOD_EXECUTE_BATCH = "execute_batch";
public static final String METHOD_EXECUTE_TRANSACTION = "execute_transaction";
public static final String METHOD_DISCONNECT = "disconnect";
public static final String METHOD_SHUTDOWN = "shutdown";
@@ -102,6 +103,7 @@ public final class AgentProtocol {
METHOD_FETCH_TABLE_READ_PAGE,
METHOD_CLOSE_TABLE_READ_SESSION,
METHOD_GET_EXPLAIN_INFO,
METHOD_EXECUTE_BATCH,
METHOD_EXECUTE_TRANSACTION,
METHOD_DISCONNECT,
METHOD_SHUTDOWN
@@ -94,6 +94,11 @@ public abstract class BaseDatabaseAgent implements DatabaseAgent {
return TransactionExecutor.executeUpdateStatements(requireConnected(), statements, schema, this::setSchemaSQL);
}
@Override
public QueryResult executeBatch(List<String> statements, String schema) {
return BatchExecutor.executeBatchStatements(requireConnected(), statements, schema, this::setSchemaSQL);
}
protected Connection requireConnected() {
Connection conn = getConnection();
if (conn == null) {
@@ -0,0 +1,117 @@
package com.dbx.agent;
import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
public final class BatchExecutor {
private BatchExecutor() {
}
public static QueryResult executeBatchStatements(
Connection conn,
List<String> statements,
String schema,
Function<String, String> setSchemaSql
) {
return unchecked(() -> {
long start = System.currentTimeMillis();
applySchema(conn, schema, setSchemaSql);
long totalAffected = 0;
int statementCount = 0;
try (Statement stmt = conn.createStatement()) {
for (String statement : statements) {
String trimmed = JdbcExecutor.trimSql(statement);
if (trimmed.isEmpty()) {
continue;
}
stmt.addBatch(trimmed);
statementCount++;
}
if (statementCount > 0) {
totalAffected = affectedRows(executeBatch(stmt));
}
} catch (BatchUpdateException e) {
long[] counts = e.getLargeUpdateCounts();
int failedIndex = counts == null ? 1 : counts.length + 1;
throw new RuntimeException("Statement " + failedIndex + " failed: " + e.getMessage(), e);
}
return new QueryResult(
Collections.emptyList(),
Collections.emptyList(),
totalAffected,
System.currentTimeMillis() - start,
false
);
});
}
private static long affectedRows(long[] updateCounts) {
long total = 0;
if (updateCounts == null) {
return total;
}
for (long count : updateCounts) {
if (count >= 0) {
total += count;
} else if (count == Statement.SUCCESS_NO_INFO) {
total += 1;
}
}
return total;
}
private static long[] executeBatch(Statement stmt) throws Exception {
try {
return stmt.executeLargeBatch();
} catch (SQLFeatureNotSupportedException | UnsupportedOperationException | AbstractMethodError e) {
int[] counts = stmt.executeBatch();
long[] largeCounts = new long[counts.length];
for (int i = 0; i < counts.length; i++) {
largeCounts[i] = counts[i];
}
return largeCounts;
}
}
private static void applySchema(Connection conn, String schema, Function<String, String> setSchemaSql) throws Exception {
if (schema == null || schema.trim().isEmpty()) {
return;
}
try {
conn.setSchema(schema);
return;
} catch (Exception | AbstractMethodError ignored) {
}
try {
conn.setCatalog(schema);
return;
} catch (Exception | AbstractMethodError ignored) {
}
String schemaSql = setSchemaSql.apply(schema);
if (schemaSql == null || schemaSql.trim().isEmpty()) {
return;
}
try (Statement stmt = conn.createStatement()) {
stmt.execute(schemaSql);
}
}
private static <T> T unchecked(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private interface ThrowingSupplier<T> {
T get() throws Exception;
}
}
@@ -151,6 +151,14 @@ public interface DatabaseAgent {
return TransactionExecutor.executeUpdateStatements(conn, statements, schema, this::setSchemaSQL);
}
default QueryResult executeBatch(List<String> statements, String schema) {
Connection conn = getConnection();
if (conn == null) {
throw new IllegalStateException("Not connected");
}
return BatchExecutor.executeBatchStatements(conn, statements, schema, this::setSchemaSQL);
}
default String setSchemaSQL(String schema) {
return "SET SCHEMA " + JdbcIdentifiers.INSTANCE.doubleQuote(schema);
}
@@ -222,6 +222,11 @@ public final class JsonRpcServer {
List<String> statements = gson.fromJson(params.get("statements"), statementsType);
return agent.executeTransaction(statements, stringOrNull(params, "schema"));
}
if (AgentProtocol.METHOD_EXECUTE_BATCH.equals(method)) {
Type statementsType = new TypeToken<List<String>>() {}.getType();
List<String> statements = gson.fromJson(params.get("statements"), statementsType);
return agent.executeBatch(statements, stringOrNull(params, "schema"));
}
if (AgentProtocol.METHOD_DISCONNECT.equals(method)) {
JdbcExecutor.INSTANCE.closeAllQuerySessions();
JdbcExecutor.INSTANCE.closeAllTableReadSessions();
@@ -59,6 +59,7 @@
"fetch_table_read_page",
"close_table_read_session",
"get_explain_info",
"execute_batch",
"execute_transaction",
"disconnect",
"shutdown"