From 834d336ed41a842a8cb3b06c63074d912dd92317 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Thu, 11 Apr 2024 15:58:05 +0300 Subject: [PATCH 1/4] [Flyway]: 1) SCAN SELECT -> SELECT FROM flyway schema history table 2) Tested Info command 3) Tested Repair command 4) Tested Validate command --- .../ydb/flywaydb/database/YdbDatabase.java | 2 +- .../flyway/database/YdbFlywayBaseTest.java | 18 +++- .../flyway/database/YdbFlywayCleanTest.java | 12 --- .../flyway/database/YdbFlywayInfoTest.java | 24 +++++ .../database/YdbFlywayMigrationTest.java | 12 --- .../YdbFlywayRepairAndValidateTest.java | 88 +++++++++++++++++++ .../V1__create_series.sql | 13 +++ .../V2__create_seasons.sql | 10 +++ .../V3__create_episodes.sql | 9 ++ 9 files changed, 159 insertions(+), 29 deletions(-) create mode 100644 flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayInfoTest.java create mode 100644 flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayRepairAndValidateTest.java create mode 100644 flyway-dialect/src/test/resources/db/migration-with-failed/V1__create_series.sql create mode 100644 flyway-dialect/src/test/resources/db/migration-with-failed/V2__create_seasons.sql create mode 100644 flyway-dialect/src/test/resources/db/migration-with-failed/V3__create_episodes.sql diff --git a/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbDatabase.java b/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbDatabase.java index 8c9ab2c..20263e0 100644 --- a/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbDatabase.java +++ b/flyway-dialect/src/main/java/tech/ydb/flywaydb/database/YdbDatabase.java @@ -69,7 +69,7 @@ public String getRawCreateScript(Table table, boolean baseline) { @Override public String getSelectStatement(Table table) { - return "SCAN SELECT " + quote("installed_rank") + return "SELECT " + quote("installed_rank") + "," + quote("version") + "," + quote("description") + "," + quote("type") diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayBaseTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayBaseTest.java index 38c50b6..129bb15 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayBaseTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayBaseTest.java @@ -19,6 +19,12 @@ */ abstract class YdbFlywayBaseTest { + private static final Set EXPECTED_ALL_SCRIPTS = Set.of( + "V1__create_series.sql", "V2__create_seasons.sql", + "V3__create_episodes.sql", "V4__load_data.sql", + "V5__create_series_title_index.sql", "V6__rename_index_title_index.sql" + ); + @RegisterExtension private static final YdbHelperExtension ydb = new YdbHelperExtension(); @@ -51,9 +57,7 @@ protected static String jdbcUrl() { protected void verifyTest() throws SQLException { try (Connection connection = DriverManager.getConnection(jdbcUrl())) { try (Statement statement = connection.createStatement()) { - assertCountTable(2, "SELECT COUNT(*) FROM series", statement); - assertCountTable(9, "SELECT COUNT(*) FROM seasons", statement); - assertCountTable(70, "SELECT COUNT(*) FROM episodes", statement); + verifyCountTables(statement); ResultSet rs = statement.executeQuery("SELECT script FROM flyway_schema_history;"); HashSet scripts = new HashSet<>(); @@ -67,8 +71,14 @@ protected void verifyTest() throws SQLException { } } + protected void verifyCountTables(Statement statement) throws SQLException { + assertCountTable(2, "SELECT COUNT(*) FROM series", statement); + assertCountTable(9, "SELECT COUNT(*) FROM seasons", statement); + assertCountTable(70, "SELECT COUNT(*) FROM episodes", statement); + } + protected Set expectedScripts() { - return Set.of(); + return EXPECTED_ALL_SCRIPTS; } @AfterEach diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayCleanTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayCleanTest.java index 50fb3fa..c59251f 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayCleanTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayCleanTest.java @@ -4,7 +4,6 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; -import java.util.Set; import org.flywaydb.core.Flyway; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -17,12 +16,6 @@ */ public class YdbFlywayCleanTest extends YdbFlywayBaseTest { - private static final Set EXPECTED_SCRIPTS = Set.of( - "V1__create_series.sql", "V2__create_seasons.sql", - "V3__create_episodes.sql", "V4__load_data.sql", - "V5__create_series_title_index.sql", "V6__rename_index_title_index.sql" - ); - @Test void cleanSchemaTest() throws SQLException { Flyway flyway = createFlyway("classpath:db/migration").cleanDisabled(false).load(); @@ -52,9 +45,4 @@ private static void assertDeletedTable(Connection connection, String sql) { @Override void checkAfterTest() { } - - @Override - protected Set expectedScripts() { - return EXPECTED_SCRIPTS; - } } diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayInfoTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayInfoTest.java new file mode 100644 index 0000000..fd0a655 --- /dev/null +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayInfoTest.java @@ -0,0 +1,24 @@ +package tech.ydb.flyway.database; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * @author Kirill Kurdyukov + */ +public class YdbFlywayInfoTest extends YdbFlywayBaseTest { + + @Test + void simpleTest() { + createFlyway("classpath:db/migration-step-3").load().migrate(); + + var flyway = createFlyway("classpath:db/migration").load(); + + var info = flyway.info(); + + assertEquals(3, info.applied().length); + assertEquals(6, info.all().length); + + flyway.migrate(); + } +} diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java index 3efa2b1..2cb1fb5 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -21,12 +20,6 @@ public class YdbFlywayMigrationTest extends YdbFlywayBaseTest { "migration-step-5", "migration", }; - private static final Set EXPECTED_SCRIPTS = Set.of( - "V1__create_series.sql", "V2__create_seasons.sql", - "V3__create_episodes.sql", "V4__load_data.sql", - "V5__create_series_title_index.sql", "V6__rename_index_title_index.sql" - ); - @Test void simpleTest() { assertTrue(createFlyway("classpath:db/migration").load().migrate().success); @@ -64,9 +57,4 @@ void evolutionConcurrencySchemaTest() throws ExecutionException, InterruptedExce } } } - - @Override - protected Set expectedScripts() { - return EXPECTED_SCRIPTS; - } } diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayRepairAndValidateTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayRepairAndValidateTest.java new file mode 100644 index 0000000..f9cdb94 --- /dev/null +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayRepairAndValidateTest.java @@ -0,0 +1,88 @@ +package tech.ydb.flyway.database; + +import java.sql.DriverManager; +import java.sql.SQLException; +import org.flywaydb.core.api.ErrorCode; +import org.flywaydb.core.internal.command.DbMigrate; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; + +/** + * @author Kirill Kurdyukov + */ +public class YdbFlywayRepairAndValidateTest extends YdbFlywayBaseTest { + + @Test + void markUnSuccessMigrationThenRepairDeletedTest() throws SQLException { + assertThrows(DbMigrate.FlywayMigrateException.class, + () -> createFlyway("classpath:db/migration-with-failed").load().migrate()); + + try (var connection = DriverManager.getConnection(jdbcUrl())) { + try (var st = connection.createStatement()) { + var rs = st.executeQuery("SELECT script FROM flyway_schema_history WHERE success = false"); + + rs.next(); + + assertEquals("V3__create_episodes.sql", rs.getString(1)); + + assertFalse(rs.next()); + } + } + + createFlyway("classpath:db/migration-step-3").load().repair(); + + try (var connection = DriverManager.getConnection(jdbcUrl())) { + try (var st = connection.createStatement()) { + var rs = st.executeQuery("SELECT COUNT(*) FROM flyway_schema_history"); + + rs.next(); + + assertEquals(2, rs.getLong(1)); + } + } + + assertTrue(createFlyway("classpath:db/migration").load().migrate().success); + } + + @Test + void updateChecksumMigrationTest() { + assertTrue(createFlyway("classpath:db/migration-step-3").load().migrate().success); + + String checksumPrev = checksum(); + + var flyway = createFlyway("classpath:db/migration-with-failed").load(); + + var validateResult = flyway.validateWithResult(); + + assertFalse(validateResult.validationSuccessful); + assertEquals("create episodes", validateResult.invalidMigrations.get(0).description); + assertEquals(ErrorCode.CHECKSUM_MISMATCH, validateResult.invalidMigrations.get(0).errorDetails.errorCode); + + flyway.repair(); + + assertNotEquals(checksumPrev, checksum()); + + flyway = createFlyway("classpath:db/migration").load(); + + flyway.repair(); + + assertEquals(checksumPrev, checksum()); + + assertTrue(flyway.migrate().success); + } + + private static String checksum() { + try (var connection = DriverManager.getConnection(jdbcUrl())) { + var rs = connection.createStatement().executeQuery("SELECT checksum FROM flyway_schema_history WHERE version = '3'"); + + rs.next(); + return rs.getString(1); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/flyway-dialect/src/test/resources/db/migration-with-failed/V1__create_series.sql b/flyway-dialect/src/test/resources/db/migration-with-failed/V1__create_series.sql new file mode 100644 index 0000000..6cc1800 --- /dev/null +++ b/flyway-dialect/src/test/resources/db/migration-with-failed/V1__create_series.sql @@ -0,0 +1,13 @@ +CREATE TABLE series -- series is the table name. +( -- Must be unique within the folder. + series_id Int64, + title Text, + series_info Text, + release_date Int64, + PRIMARY KEY (series_id) -- The primary key is a column or + -- combination of columns that uniquely identifies + -- each table row (contains only + -- non-repeating values). A table can have + -- only one primary key. For every table + -- in YDB, the primary key is required. +); \ No newline at end of file diff --git a/flyway-dialect/src/test/resources/db/migration-with-failed/V2__create_seasons.sql b/flyway-dialect/src/test/resources/db/migration-with-failed/V2__create_seasons.sql new file mode 100644 index 0000000..24b9705 --- /dev/null +++ b/flyway-dialect/src/test/resources/db/migration-with-failed/V2__create_seasons.sql @@ -0,0 +1,10 @@ + +CREATE TABLE seasons +( + series_id Uint64, + season_id Uint64, + title Utf8, + first_aired Uint64, + last_aired Uint64, + PRIMARY KEY (series_id, season_id) +); \ No newline at end of file diff --git a/flyway-dialect/src/test/resources/db/migration-with-failed/V3__create_episodes.sql b/flyway-dialect/src/test/resources/db/migration-with-failed/V3__create_episodes.sql new file mode 100644 index 0000000..e7a4b6f --- /dev/null +++ b/flyway-dialect/src/test/resources/db/migration-with-failed/V3__create_episodes.sql @@ -0,0 +1,9 @@ +CREATE TABLE episodes +( + series_id STRANGE, + season_id Uint64, + episode_id Uint64, + title Utf8, + air_date Uint64, + PRIMARY KEY (series_id, season_id, episode_id) +); \ No newline at end of file From 0c679a8b3767c9db47655e9a39bc8acbdbf2cbf6 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Thu, 11 Apr 2024 16:01:47 +0300 Subject: [PATCH 2/4] [Flyway]: 1) SCAN SELECT -> SELECT FROM flyway schema history table 2) Tested Info command 3) Tested Repair command 4) Tested Validate command --- .../database/YdbFlywayMigrationTest.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java index 2cb1fb5..23855c7 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java @@ -36,24 +36,26 @@ void evolutionSchemaTest() { void evolutionConcurrencySchemaTest() throws ExecutionException, InterruptedException { int threadPoolSize = 10; - ExecutorService threadPool = Executors.newFixedThreadPool(threadPoolSize); - - for (int migrationStep = 0; migrationStep < EVOLUTION_SCHEMA_MIGRATION_DIRS.length; migrationStep++) { - List> taskFutures = new ArrayList<>(); - - for (int i = 0; i < threadPoolSize * 2; i++) { - int finalMigrationStep = migrationStep; - - taskFutures.add( - threadPool.submit(() -> assertTrue( - createFlyway("classpath:db/" + EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep]) - .load().migrate().success - )) - ); - } - - for (Future taskFuture : taskFutures) { - taskFuture.get(); + try (ExecutorService threadPool = Executors.newFixedThreadPool(threadPoolSize)) { + + for (int migrationStep = 0; migrationStep < EVOLUTION_SCHEMA_MIGRATION_DIRS.length; migrationStep++) { + List> taskFutures = new ArrayList<>(); + + for (int i = 0; i < threadPoolSize * 2; i++) { + int finalMigrationStep = migrationStep; + + taskFutures.add( + threadPool.submit(() -> assertTrue( + createFlyway("classpath:db/" + + EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep]) + .load().migrate().success + )) + ); + } + + for (Future taskFuture : taskFutures) { + taskFuture.get(); + } } } } From 241800762d2cb284432c4124c249d0b89d02a5c2 Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Thu, 11 Apr 2024 16:08:09 +0300 Subject: [PATCH 3/4] [Flyway]: 1) SCAN SELECT -> SELECT FROM flyway schema history table 2) Tested Info command 3) Tested Repair command 4) Tested Validate command --- .../database/YdbFlywayMigrationTest.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java index 23855c7..05f565d 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java @@ -36,26 +36,25 @@ void evolutionSchemaTest() { void evolutionConcurrencySchemaTest() throws ExecutionException, InterruptedException { int threadPoolSize = 10; - try (ExecutorService threadPool = Executors.newFixedThreadPool(threadPoolSize)) { - - for (int migrationStep = 0; migrationStep < EVOLUTION_SCHEMA_MIGRATION_DIRS.length; migrationStep++) { - List> taskFutures = new ArrayList<>(); - - for (int i = 0; i < threadPoolSize * 2; i++) { - int finalMigrationStep = migrationStep; - - taskFutures.add( - threadPool.submit(() -> assertTrue( - createFlyway("classpath:db/" + - EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep]) - .load().migrate().success - )) - ); - } - - for (Future taskFuture : taskFutures) { - taskFuture.get(); - } + ExecutorService threadPool = Executors.newFixedThreadPool(threadPoolSize); + + for (int migrationStep = 0; migrationStep < EVOLUTION_SCHEMA_MIGRATION_DIRS.length; migrationStep++) { + List> taskFutures = new ArrayList<>(); + + for (int i = 0; i < threadPoolSize * 2; i++) { + int finalMigrationStep = migrationStep; + + taskFutures.add( + threadPool.submit(() -> assertTrue( + createFlyway("classpath:db/" + + EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep]) + .load().migrate().success + )) + ); + } + + for (Future taskFuture : taskFutures) { + taskFuture.get(); } } } From 0c6158f133a88a0ae32ab7664beef63892a8373f Mon Sep 17 00:00:00 2001 From: Kirill Kurdyukov Date: Thu, 11 Apr 2024 16:10:08 +0300 Subject: [PATCH 4/4] [Flyway]: 1) SCAN SELECT -> SELECT FROM flyway schema history table 2) Tested Info command 3) Tested Repair command 4) Tested Validate command --- .../java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java index 05f565d..7847044 100644 --- a/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java +++ b/flyway-dialect/src/test/java/tech/ydb/flyway/database/YdbFlywayMigrationTest.java @@ -47,8 +47,8 @@ void evolutionConcurrencySchemaTest() throws ExecutionException, InterruptedExce taskFutures.add( threadPool.submit(() -> assertTrue( createFlyway("classpath:db/" + - EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep]) - .load().migrate().success + EVOLUTION_SCHEMA_MIGRATION_DIRS[finalMigrationStep] + ).load().migrate().success )) ); }