This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 0985b7c2e6e Fix stale generated values in prepared statement
executeBatch (#38160)
0985b7c2e6e is described below
commit 0985b7c2e6e7aa6f28c0077c2113de8ccbcfcb80
Author: Aviral Garg <[email protected]>
AuthorDate: Mon Feb 23 18:18:23 2026 +0530
Fix stale generated values in prepared statement executeBatch (#38160)
* jdbc: clear stale prepared-statement batch generated values
* jdbc: reorder prepared statement test helper overloads
---
.../statement/ShardingSpherePreparedStatement.java | 11 +++++++++
.../ShardingSpherePreparedStatementTest.java | 27 +++++++++++-----------
2 files changed, 25 insertions(+), 13 deletions(-)
diff --git
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index e3ba83d58cf..73a009886fb 100644
---
a/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++
b/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -101,6 +101,8 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
private final Collection<Comparable<?>> generatedValues = new
LinkedList<>();
+ private boolean hasBatchGeneratedValues;
+
private final boolean statementsCacheable;
private Map<String, Integer> columnLabelAndIndexMap;
@@ -285,6 +287,7 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
statements.clear();
parameterSets.clear();
generatedValues.clear();
+ hasBatchGeneratedValues = false;
}
private Optional<GeneratedKeyContext> findGeneratedKey() {
@@ -318,6 +321,10 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
@Override
public void addBatch() {
+ if (!hasBatchGeneratedValues) {
+ generatedValues.clear();
+ hasBatchGeneratedValues = true;
+ }
currentResultSet = null;
QueryContext queryContext = createQueryContext();
this.queryContext = queryContext;
@@ -329,6 +336,9 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
@Override
public int[] executeBatch() throws SQLException {
try {
+ if (!hasBatchGeneratedValues) {
+ generatedValues.clear();
+ }
return executeBatchExecutor.executeBatch(usedDatabase,
sqlStatementContext, generatedValues, statementOption,
(StatementAddCallback<PreparedStatement>) (statements,
parameterSets) -> this.statements.addAll(statements),
this::replaySetParameter,
@@ -352,6 +362,7 @@ public final class ShardingSpherePreparedStatement extends
AbstractPreparedState
closeCurrentBatchGeneratedKeysResultSet();
executeBatchExecutor.clear();
clearParameters();
+ hasBatchGeneratedValues = false;
}
private void closeCurrentBatchGeneratedKeysResultSet() {
diff --git
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
index 88897b80408..1403f9d5dc6 100644
---
a/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
+++
b/jdbc/src/test/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatementTest.java
@@ -62,19 +62,7 @@ class ShardingSpherePreparedStatementTest {
@SuppressWarnings("unchecked")
@Test
void assertClearBatchResetsCachedGeneratedKeysResultSet() throws
SQLException, ReflectiveOperationException {
- ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
-
when(database.getProtocolType()).thenReturn(TypedSPILoader.getService(DatabaseType.class,
"SQL92"));
- when(database.getRuleMetaData()).thenReturn(new
RuleMetaData(Collections.emptyList()));
- ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class);
- when(metaData.getDatabase("foo_db")).thenReturn(database);
- when(metaData.getGlobalRuleMetaData()).thenReturn(new
RuleMetaData(Arrays.asList(
- new SQLParserRule(new
DefaultSQLParserRuleConfigurationBuilder().build()),
- new SQLFederationRule(new
DefaultSQLFederationRuleConfigurationBuilder().build(),
Collections.emptyList()))));
- when(metaData.getProps()).thenReturn(new ConfigurationProperties(new
Properties()));
- ShardingSphereConnection connection =
mock(ShardingSphereConnection.class, RETURNS_DEEP_STUBS);
-
when(connection.getContextManager().getMetaDataContexts().getMetaData()).thenReturn(metaData);
- when(connection.getCurrentDatabaseName()).thenReturn("foo_db");
- ShardingSpherePreparedStatement preparedStatement = new
ShardingSpherePreparedStatement(connection, "SELECT 1",
Statement.RETURN_GENERATED_KEYS);
+ ShardingSpherePreparedStatement preparedStatement =
createPreparedStatement();
ResultSet cachedResultSet = new GeneratedKeysResultSet();
Plugins.getMemberAccessor().set(ShardingSpherePreparedStatement.class.getDeclaredField("currentBatchGeneratedKeysResultSet"),
preparedStatement, cachedResultSet);
((Collection<Comparable<?>>)
Plugins.getMemberAccessor().get(ShardingSpherePreparedStatement.class.getDeclaredField("generatedValues"),
preparedStatement)).add(1L);
@@ -84,6 +72,15 @@ class ShardingSpherePreparedStatementTest {
assertFalse(actual.isClosed());
}
+ @SuppressWarnings("unchecked")
+ @Test
+ void assertExecuteBatchClearsGeneratedValuesWithoutPendingBatches() throws
SQLException, ReflectiveOperationException {
+ ShardingSpherePreparedStatement preparedStatement =
createPreparedStatement();
+ ((Collection<Comparable<?>>)
Plugins.getMemberAccessor().get(ShardingSpherePreparedStatement.class.getDeclaredField("generatedValues"),
preparedStatement)).add(1L);
+ preparedStatement.executeBatch();
+ assertFalse(preparedStatement.getGeneratedKeys().next());
+ }
+
@Test
void assertGetGeneratedKeysByDialectGeneratedKeyColumn() throws
SQLException {
ShardingSpherePreparedStatement preparedStatement =
createPreparedStatement(TypedSPILoader.getService(DatabaseType.class, "MySQL"));
@@ -101,6 +98,10 @@ class ShardingSpherePreparedStatementTest {
verify(generatedKeys, never()).getObject(1);
}
+ private ShardingSpherePreparedStatement createPreparedStatement() throws
SQLException {
+ return
createPreparedStatement(TypedSPILoader.getService(DatabaseType.class, "SQL92"));
+ }
+
private ShardingSpherePreparedStatement createPreparedStatement(final
DatabaseType databaseType) throws SQLException {
ShardingSphereMetaData metaData = createMetaData(databaseType);
ShardingSphereConnection connection =
mock(ShardingSphereConnection.class, RETURNS_DEEP_STUBS);