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);

Reply via email to