Skip to content

Commit 0515e87

Browse files
authored
fix[PDI-20410]: Refactor Database class to replace ReentrantLock with synchronized block for connection handling (#10073)
* fix[PDI-20410]: Refactor Database class to replace ReentrantLock with synchronized block for connection handling * test: fix failing unit test
1 parent 454eca2 commit 0515e87

File tree

2 files changed

+19
-20
lines changed

2 files changed

+19
-20
lines changed

core/src/main/java/org/pentaho/di/core/database/Database.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@
4444
import java.util.Map;
4545
import java.util.Properties;
4646
import java.util.Set;
47-
import java.util.concurrent.locks.Lock;
48-
import java.util.concurrent.locks.ReentrantLock;
4947

5048
import org.apache.commons.lang.StringUtils;
5149
import org.apache.commons.vfs2.FileObject;
@@ -181,8 +179,6 @@ public class Database implements VariableSpace, LoggingObjectInterface, Closeabl
181179
private DataSource dataSource;
182180
private String ownerName;
183181

184-
private static final Lock lock = new ReentrantLock();
185-
186182
static {
187183
initValueMetaPluginClasses();
188184
// listen for changes to make sure the valueMetaPluginClasses list is accurate.
@@ -2732,26 +2728,27 @@ public Object[] getRow( ResultSet rs, ResultSetMetaData dummy, RowMetaInterface
27322728
long startTime = System.currentTimeMillis();
27332729

27342730
try {
2735-
lock.lock();
2736-
2737-
int nrcols = rowInfo.size();
2738-
Object[] data = RowDataUtil.allocateRowData( nrcols );
2731+
// PDI-19750 - synchronize on the connection to prevent data inconsistency
2732+
// when multiple Database objects share the same connection and access ResultSets concurrently
2733+
synchronized ( connection ) {
2734+
int nrcols = rowInfo.size();
2735+
Object[] data = RowDataUtil.allocateRowData( nrcols );
27392736

2740-
if ( rs.next() ) {
2741-
for ( int i = 0; i < nrcols; i++ ) {
2742-
ValueMetaInterface val = rowInfo.getValueMeta( i );
2737+
if ( rs.next() ) {
2738+
for ( int i = 0; i < nrcols; i++ ) {
2739+
ValueMetaInterface val = rowInfo.getValueMeta( i );
27432740

2744-
data[ i ] = databaseMeta.getValueFromResultSet( rs, val, i );
2741+
data[ i ] = databaseMeta.getValueFromResultSet( rs, val, i );
2742+
}
2743+
} else {
2744+
data = null;
27452745
}
2746-
} else {
2747-
data = null;
2748-
}
27492746

2750-
return data;
2747+
return data;
2748+
}
27512749
} catch ( Exception ex ) {
27522750
throw new KettleDatabaseException( "Couldn't get row from result set", ex );
27532751
} finally {
2754-
lock.unlock();
27552752
if ( log.isGatheringMetrics() ) {
27562753
long time = System.currentTimeMillis() - startTime;
27572754
log.snap( Metrics.METRIC_DATABASE_GET_ROW_SUM_TIME, databaseMeta.getName(), time );

core/src/test/java/org/pentaho/di/core/database/DatabaseTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,11 @@ public void testGetLookupCallPSpassed() throws SQLException, KettleDatabaseExcep
270270
when( rsMetaData.getColumnCount() ).thenReturn( 0 );
271271
when( ps.getMetaData() ).thenReturn( rsMetaData );
272272

273-
Database db = new Database( log, meta );
274-
db.getLookup( ps );
275-
verify( rsMetaData, times( 1 ) ).getColumnCount();
273+
try ( Database db = new Database( log, meta ) ) {
274+
db.setConnection( conn );
275+
db.getLookup( ps );
276+
verify( rsMetaData, times( 1 ) ).getColumnCount();
277+
}
276278
}
277279

278280
@Test

0 commit comments

Comments
 (0)