From a26c5dc45146786b7bb853df66c280a6824f9997 Mon Sep 17 00:00:00 2001 From: Alexandr Gorshenin Date: Mon, 23 Jun 2025 16:07:20 +0100 Subject: [PATCH 1/3] Fix resource leaking in flyway-dialect --- .../tech/ydb/flywaydb/database/YdbSchema.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbSchema.java b/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbSchema.java index a41f7ea..30e1c2e 100644 --- a/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbSchema.java +++ b/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbSchema.java @@ -1,10 +1,12 @@ package tech.ydb.flywaydb.database; +import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; + import org.flywaydb.core.internal.database.base.Schema; import org.flywaydb.core.internal.jdbc.JdbcTemplate; @@ -75,15 +77,13 @@ public String toString() { } private List schemaTables() throws SQLException { - ResultSet rs = jdbcTemplate.getConnection().getMetaData() - .getTables(null, name, null, new String[]{"TABLE"}); - - List tables = new ArrayList<>(); - - while (rs.next()) { - tables.add(database.quote(rs.getString("TABLE_NAME"))); + DatabaseMetaData md = jdbcTemplate.getConnection().getMetaData(); + try (ResultSet rs = md.getTables(null, name, null, new String[]{"TABLE"})) { + List tables = new ArrayList<>(); + while (rs.next()) { + tables.add(database.quote(rs.getString("TABLE_NAME"))); + } + return tables; } - - return tables; } } From 92338e483ce925d766d491c613d620d3cd296331 Mon Sep 17 00:00:00 2001 From: Alexandr Gorshenin Date: Mon, 23 Jun 2025 16:16:30 +0100 Subject: [PATCH 2/3] Fix resource leaking in Liquibase dialect --- .../liquibase/change/InsertDataChangeYdb.java | 16 ++++++------- .../liquibase/change/LoadDataChangeYdb.java | 23 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/InsertDataChangeYdb.java b/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/InsertDataChangeYdb.java index 152fc43..2bd0c4a 100644 --- a/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/InsertDataChangeYdb.java +++ b/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/InsertDataChangeYdb.java @@ -6,6 +6,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; + import liquibase.change.ChangeMetaData; import liquibase.change.ColumnConfig; import liquibase.change.DatabaseChange; @@ -34,14 +35,13 @@ public SqlStatement[] generateStatements(Database database) { try { JdbcConnection jdbcConnection = (JdbcConnection) database.getConnection(); - ResultSet resultSet = jdbcConnection.getMetaData() - .getColumns(null, null, getTableName(), null); - - while (resultSet.next()) { - columnToLiquibaseDataType.put( - resultSet.getString("COLUMN_NAME").toLowerCase(), - DataTypeFactory.getInstance() - .fromDescription(resultSet.getString("TYPE_NAME"), database)); + try (ResultSet rs = jdbcConnection.getMetaData().getColumns(null, null, getTableName(), null)) { + while (rs.next()) { + columnToLiquibaseDataType.put( + rs.getString("COLUMN_NAME").toLowerCase(), + DataTypeFactory.getInstance().fromDescription(rs.getString("TYPE_NAME"), database) + ); + } } StringBuilder yqlInsert = new StringBuilder() diff --git a/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/LoadDataChangeYdb.java b/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/LoadDataChangeYdb.java index a7edcb8..e553c78 100644 --- a/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/LoadDataChangeYdb.java +++ b/liquibase-dialect/src/main/java/tech/ydb/liquibase/change/LoadDataChangeYdb.java @@ -1,6 +1,5 @@ package tech.ydb.liquibase.change; -import com.opencsv.exceptions.CsvMalformedLineException; import java.io.IOException; import java.sql.ResultSet; import java.util.ArrayList; @@ -9,6 +8,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; + +import com.opencsv.exceptions.CsvMalformedLineException; import liquibase.Scope; import liquibase.change.ChangeMetaData; import liquibase.change.DatabaseChange; @@ -23,6 +24,7 @@ import liquibase.statement.core.InsertStatement; import liquibase.statement.core.RawSqlStatement; import liquibase.util.csv.CSVReader; + import tech.ydb.liquibase.database.YdbDatabase; /** @@ -60,17 +62,16 @@ public SqlStatement[] generateStatements(Database database) { } JdbcConnection jdbcConnection = (JdbcConnection) database.getConnection(); - ResultSet resultSet = jdbcConnection.getMetaData() - .getColumns(null, null, tableName, null); - - while (resultSet.next()) { - columnToLiquibaseDataType.put( - resultSet.getString("COLUMN_NAME").toLowerCase(), - DataTypeFactory.getInstance() - .fromDescription(resultSet.getString("TYPE_NAME"), database)); - } + try (ResultSet resultSet = jdbcConnection.getMetaData().getColumns(null, null, tableName, null)) { + while (resultSet.next()) { + columnToLiquibaseDataType.put( + resultSet.getString("COLUMN_NAME").toLowerCase(), + DataTypeFactory.getInstance() + .fromDescription(resultSet.getString("TYPE_NAME"), database)); + } - return getSqlStatements(database, reader, headers); + return getSqlStatements(database, reader, headers); + } } catch (CsvMalformedLineException e) { throw new RuntimeException("Error parsing " + getRelativeTo() + " on line " + e.getLineNumber() + ": " + e.getMessage()); } catch (UnexpectedLiquibaseException ule) { From 4056795e12b990e8f63e6f5e87773f6b9aa88aae Mon Sep 17 00:00:00 2001 From: Alexandr Gorshenin Date: Mon, 23 Jun 2025 16:19:09 +0100 Subject: [PATCH 3/3] Fix resource leaking in YDB shedlock --- .../lock/provider/YdbJDBCLockProvider.java | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/shedlock-ydb/src/main/java/tech/ydb/lock/provider/YdbJDBCLockProvider.java b/shedlock-ydb/src/main/java/tech/ydb/lock/provider/YdbJDBCLockProvider.java index c15935e..405964d 100644 --- a/shedlock-ydb/src/main/java/tech/ydb/lock/provider/YdbJDBCLockProvider.java +++ b/shedlock-ydb/src/main/java/tech/ydb/lock/provider/YdbJDBCLockProvider.java @@ -2,7 +2,9 @@ import java.sql.SQLException; import java.util.Optional; + import javax.sql.DataSource; + import net.javacrumbs.shedlock.core.LockConfiguration; import net.javacrumbs.shedlock.core.LockProvider; import net.javacrumbs.shedlock.core.SimpleLock; @@ -31,33 +33,30 @@ public Optional lock(LockConfiguration lockConfiguration) { try { connection.setAutoCommit(false); - var selectPS = connection.prepareStatement("SELECT locked_by, lock_until FROM shedlock " + - "WHERE name = ? AND lock_until > CurrentUtcTimestamp()"); - - selectPS.setString(1, lockConfiguration.getName()); - - try (var rs = selectPS.executeQuery()) { - if (rs.next()) { - LOGGER.debug("Instance[{}] acquire lock is failed. Leader is {}, lock_until = {}", - LOCKED_BY, rs.getString(1), rs.getString(2)); - return Optional.empty(); + try (var selectPS = connection.prepareStatement("SELECT locked_by, lock_until FROM shedlock " + + "WHERE name = ? AND lock_until > CurrentUtcTimestamp()")) { + selectPS.setString(1, lockConfiguration.getName()); + try (var rs = selectPS.executeQuery()) { + if (rs.next()) { + LOGGER.debug("Instance[{}] acquire lock is failed. Leader is {}, lock_until = {}", + LOCKED_BY, rs.getString(1), rs.getString(2)); + return Optional.empty(); + } } } - var upsertPS = connection.prepareStatement("" + + try (var upsertPS = connection.prepareStatement("" + "UPSERT INTO shedlock(name, lock_until, locked_at, locked_by) " + "VALUES (?, Unwrap(CurrentUtcTimestamp() + ?), CurrentUtcTimestamp(), ?)" - ); - - upsertPS.setObject(1, lockConfiguration.getName()); - upsertPS.setObject(2, lockConfiguration.getLockAtMostFor()); - upsertPS.setObject(3, LOCKED_BY); - upsertPS.execute(); + )) { + upsertPS.setObject(1, lockConfiguration.getName()); + upsertPS.setObject(2, lockConfiguration.getLockAtMostFor()); + upsertPS.setObject(3, LOCKED_BY); + upsertPS.execute(); + } connection.commit(); - LOGGER.debug("Instance[{}] is leader", LOCKED_BY); - return Optional.of(new YdbJDBCLock(lockConfiguration.getName(), dataSource)); } finally { connection.setAutoCommit(autoCommit);