diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java new file mode 100644 index 00000000000000..da86f3817802d9 --- /dev/null +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest.java @@ -0,0 +1,40 @@ +package io.quarkus.flyway.test; + +import static org.junit.jupiter.api.Assertions.assertNull; + +import javax.inject.Inject; + +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.MigrationInfo; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest { + @Inject + Flyway flyway; + + static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer + .withDbName("quarkus-baseline-at-start-existing-schema-history") + .withPort(11309) + .withInitSqlFile("src/test/resources/h2-init-schema-history-table.sql"); + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setBeforeAllCustomizer(customizer::startH2) + .setAfterAllCustomizer(customizer::stopH2) + .withApplicationRoot((jar) -> jar + .addClass(FlywayH2TestCustomizer.class) + .addAsResource("db/migration/V1.0.0__Quarkus.sql") + .addAsResource("baseline-at-start-existing-schema-history-table-config.properties", + "application.properties")); + + @Test + @DisplayName("Baseline at start is not executed against existing schema-history-table") + public void testFlywayConfigInjection() { + MigrationInfo migrationInfo = flyway.info().current(); + assertNull(migrationInfo, "Flyway baseline was executed on existing schema history table"); + } +} diff --git a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartTest.java b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartTest.java index 3dbcfc99eeba0a..be394f543fa20c 100644 --- a/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartTest.java +++ b/extensions/flyway/deployment/src/test/java/io/quarkus/flyway/test/FlywayExtensionBaselineAtStartTest.java @@ -25,7 +25,7 @@ public class FlywayExtensionBaselineAtStartTest { .addAsResource("baseline-at-start-config.properties", "application.properties")); @Test - @DisplayName("Baseline at start correctly") + @DisplayName("Baseline at start is executed against empty schema") public void testFlywayConfigInjection() { MigrationInfo migrationInfo = flyway.info().current(); assertNotNull(migrationInfo, "No Flyway migration was executed"); diff --git a/extensions/flyway/deployment/src/test/resources/baseline-at-start-config.properties b/extensions/flyway/deployment/src/test/resources/baseline-at-start-config.properties index 5a68715600a84c..b476e073dc59f1 100644 --- a/extensions/flyway/deployment/src/test/resources/baseline-at-start-config.properties +++ b/extensions/flyway/deployment/src/test/resources/baseline-at-start-config.properties @@ -1,7 +1,7 @@ quarkus.datasource.db-kind=h2 quarkus.datasource.username=sa quarkus.datasource.password=sa -quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test-quarkus-baseline-at-start;DB_CLOSE_DELAY=-1 +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-baseline-at-start;DB_CLOSE_DELAY=-1 # Flyway config properties quarkus.flyway.baseline-at-start=true diff --git a/extensions/flyway/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties b/extensions/flyway/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties new file mode 100644 index 00000000000000..23d6fbbc2303cb --- /dev/null +++ b/extensions/flyway/deployment/src/test/resources/baseline-at-start-existing-schema-history-table-config.properties @@ -0,0 +1,8 @@ +quarkus.datasource.db-kind=h2 +quarkus.datasource.username=sa +quarkus.datasource.password=sa +quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11309/mem:quarkus-baseline-at-start-existing-schema-history;DB_CLOSE_DELAY=-1 + +# Flyway config properties +quarkus.flyway.baseline-at-start=true +quarkus.flyway.baseline-version=1.0.1 \ No newline at end of file diff --git a/extensions/flyway/deployment/src/test/resources/h2-init-schema-history-table.sql b/extensions/flyway/deployment/src/test/resources/h2-init-schema-history-table.sql new file mode 100644 index 00000000000000..fafb04b764139d --- /dev/null +++ b/extensions/flyway/deployment/src/test/resources/h2-init-schema-history-table.sql @@ -0,0 +1,13 @@ +CREATE TABLE "flyway_schema_history" ( + "installed_rank" integer NOT NULL, + "version" character varying(50), + "description" character varying(200) NOT NULL, + "type" character varying(20) NOT NULL, + "script" character varying(1000) NOT NULL, + "checksum" integer, + "installed_by" character varying(100) NOT NULL, + "installed_on" timestamp without time zone DEFAULT now() NOT NULL, + "execution_time" integer NOT NULL, + "success" boolean NOT NULL, + CONSTRAINT flyway_schema_history_pk PRIMARY KEY ("installed_rank") +); \ No newline at end of file diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java index fcb268d7ebfd05..7433f30cb5390d 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java @@ -113,16 +113,18 @@ public static FlywayDataSourceRuntimeConfig defaultConfig() { public boolean repairAtStart; /** - * call baseline when migrate is executed against a non-empty schema with no metadata table. - * This schema will then be baselined with the baselineVersion before executing the migrations. - * Only migrations above baselineVersion will then be applied + * true to execute Flyway baseline before migrations This flag is ignored if the flyway_schema_history table exist in the + * current schema or if the current schema is empty. + * Note that this will not automatically call migrate, you must either enable baselineAtStart or programmatically call + * flyway.migrate(). */ @ConfigItem public boolean baselineOnMigrate; /** - * true to execute Flyway baseline automatically when the application starts when executed against an empty schema, false - * otherwise. + * true to execute Flyway baseline automatically when the application starts. + * This flag is ignored if the flyway_schema_history table exist in the current schema. + * This will work even if the current schema is empty. */ @ConfigItem public boolean baselineAtStart; diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java index fbb20d083df4eb..96abb43e161356 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java @@ -4,15 +4,22 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.function.Supplier; import javax.enterprise.inject.UnsatisfiedResolutionException; import javax.sql.DataSource; import org.flywaydb.core.Flyway; +import org.flywaydb.core.FlywayExecutor; import org.flywaydb.core.api.callback.Callback; import org.flywaydb.core.api.migration.JavaMigration; +import org.flywaydb.core.api.output.BaselineResult; +import org.flywaydb.core.internal.callback.CallbackExecutor; +import org.flywaydb.core.internal.database.base.Database; +import org.flywaydb.core.internal.database.base.Schema; +import org.flywaydb.core.internal.jdbc.StatementInterceptor; +import org.flywaydb.core.internal.resolver.CompositeMigrationResolver; +import org.flywaydb.core.internal.schemahistory.SchemaHistory; import org.jboss.logging.Logger; import io.quarkus.agroal.runtime.DataSources; @@ -70,13 +77,13 @@ public Flyway get() { public void doStartActions() { for (FlywayContainer flywayContainer : FLYWAY_CONTAINERS) { - if (flywayContainer.isBaselineAtStart() && - Objects.isNull(flywayContainer.getFlyway().info().current())) { - flywayContainer.getFlyway().baseline(); - } if (flywayContainer.isCleanAtStart()) { flywayContainer.getFlyway().clean(); } + if (flywayContainer.isBaselineAtStart()) { + new FlywayExecutor(flywayContainer.getFlyway().getConfiguration()) + .execute(new BaselineCommand(flywayContainer.getFlyway()), true); + } if (flywayContainer.isRepairAtStart()) { flywayContainer.getFlyway().repair(); } @@ -85,4 +92,21 @@ public void doStartActions() { } } } + + static class BaselineCommand implements FlywayExecutor.Command { + BaselineCommand(Flyway flyway) { + this.flyway = flyway; + } + + final Flyway flyway; + + @Override + public BaselineResult execute(CompositeMigrationResolver cmr, SchemaHistory schemaHistory, Database d, + Schema defaultSchema, Schema[] s, CallbackExecutor ce, StatementInterceptor si) { + if (!schemaHistory.exists()) { + return flyway.baseline(); + } + return null; + } + } }