All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.ght1pc9kc.testy.jooq.WithFlywaySchemaHistory Maven / Gradle / Ivy

The newest version!
package fr.ght1pc9kc.testy.jooq;

import fr.ght1pc9kc.testy.jooq.model.FlywayVersion;
import lombok.EqualsAndHashCode;
import org.flywaydb.core.api.configuration.ClassicConfiguration;
import org.jetbrains.annotations.VisibleForTesting;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.InsertValuesStepN;
import org.jooq.Record;
import org.jooq.SQLDialect;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.impl.DSL;
import org.jooq.impl.Internal;
import org.jooq.impl.SQLDataType;
import org.jooq.impl.TableImpl;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

import javax.sql.DataSource;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Extension used to initialize a Flyway history in a database.
 * A table is created into a schema provided by {@link DatasourceExtension}.
 * History rows can be inserted with model {@link FlywayVersion}.
 * 

Example of use with default flyway history table

*

 *     private static final WithInMemoryDatasource wDataSource = WithInMemoryDatasource.builder()
 *             .setCatalog("test_db")
 *             .build();
 *     private static final WithFlywaySchemaHistory wFlywayHistory = WithFlywaySchemaHistory.builder(wDataSource)
 *             .addVersion(FlywayVersion.builder()
 *                              .version("1.0")
 *                              .script("V1_0__my_custom_script.sql")
 *                              .type(MigrationType.SQL)
 *                              .description("my custom script")
 *                              .checksum(1230145397)
 *                              .installedBy("test_db")
 *                              .installedOn(Instant.now())
 *                              .success(true)
 *                              .build)
 *             .build();
 *
 *    {@literal @}RegisterExtension
 *     static final ChainedExtension chain = ChainedExtension.outer(wDataSource)
 *             .append(wFlywayHistory)
 *             .register();
 * 
*

A customized history table name can also be defined.

*

 *     private static final WithInMemoryDatasource wDataSource = WithInMemoryDatasource.builder()
 *             .setCatalog("test_db")
 *             .build();
 *     private static final WithFlywaySchemaHistory wFlywayHistory = WithFlywaySchemaHistory.builder(wDataSource)
 *             .setTableName("my_custom_flyway_history")
 *             .addVersion(FlywayVersion.builder()
 *                              .version("1.0")
 *                              .script("V1_0__my_custom_script.sql")
 *                              .type(MigrationType.SQL)
 *                              .description("my custom script")
 *                              .checksum(1230145397)
 *                              .installedBy("test_db")
 *                              .installedOn(Instant.now())
 *                              .success(true)
 *                              .build)
 *             .build();
 *
 *    {@literal @}RegisterExtension
 *     static final ChainedExtension chain = ChainedExtension.outer(wDataSource)
 *             .append(wFlywayHistory)
 *             .register();
 * 
*/ public final class WithFlywaySchemaHistory implements BeforeAllCallback, BeforeEachCallback { @VisibleForTesting static final String DEFAULT_TABLE_NAME = new ClassicConfiguration().getTable(); private final DatasourceExtension dataSourceExtension; private final List versions; private final String tableName; private WithFlywaySchemaHistory(DatasourceExtension dataSourceExtension, List versions, String tableName) { this.dataSourceExtension = dataSourceExtension; this.versions = List.copyOf(versions); this.tableName = tableName; } @Override public void beforeAll(ExtensionContext extensionContext) { final DataSource dataSource = getDataSource(extensionContext); final DSLContext dslContext = DSL.using(dataSource, SQLDialect.H2); final FlywayTable flywayTable = getFlywayTable(extensionContext); dslContext.dropTableIfExists(flywayTable).execute(); dslContext.createTable(flywayTable).columns(flywayTable.allFields).execute(); } @Override public void beforeEach(ExtensionContext extensionContext) { final DataSource dataSource = getDataSource(extensionContext); final FlywayTable flywayTable = getFlywayTable(extensionContext); final DSLContext dslContext = DSL.using(dataSource, SQLDialect.H2); dslContext.deleteFrom(flywayTable).execute(); final AtomicInteger installedRank = new AtomicInteger(); final InsertValuesStepN query = dslContext.insertInto(flywayTable) .columns(flywayTable.allFields); versions.stream() .map(version -> Arrays.asList(installedRank.addAndGet(1), version.version, version.description, version.type, version.script, version.checksum, version.installedBy, version.installationDate, version.executionTime, version.success )).forEach(query::values); query.execute(); } private DataSource getDataSource(ExtensionContext context) { return Objects.requireNonNull(dataSourceExtension.getDataSource(context), "DataSource not found in Store !"); } private FlywayTable getFlywayTable(ExtensionContext context) { final String schema = Objects.requireNonNull(dataSourceExtension.getCatalog(context), "DB schema not found in Store !"); return new FlywayTable(tableName, schema); } /** * Create a builder for this class. * * @param datasourceExtension {@link DatasourceExtension} to get the schema where Flyway history table will be created. * @return {@link WithFlywaySchemaHistoryBuilder}. */ public static WithFlywaySchemaHistoryBuilder builder(DatasourceExtension datasourceExtension) { return new WithFlywaySchemaHistoryBuilder(datasourceExtension); } /** * Builder class for {@link WithFlywaySchemaHistory} extension. */ public static final class WithFlywaySchemaHistoryBuilder { private final DatasourceExtension dataSourceExtension; private String tableName = DEFAULT_TABLE_NAME; private final List allVersions = new ArrayList<>(); WithFlywaySchemaHistoryBuilder(DatasourceExtension datasourceExtension) { this.dataSourceExtension = datasourceExtension; } /** * Define a customized name for the history table. * If not set, the name of the table will be given by Flyway basic configuration. * * @param tableName Name to set for the history table. * @return Builder instance. */ public WithFlywaySchemaHistoryBuilder setTableName(String tableName) { this.tableName = tableName; return this; } /** * Add a version into the history. * * @param version {@link FlywayVersion} to insert into the history table. * @return Builder instance. */ public WithFlywaySchemaHistoryBuilder addVersion(FlywayVersion version) { allVersions.add(version); return this; } /** * Add many versions into the history. * * @param versions {@link FlywayVersion} to insert into the history table. * @return Builder instance. */ public WithFlywaySchemaHistoryBuilder addVersions(FlywayVersion... versions) { allVersions.addAll(Arrays.asList(versions)); return this; } /** * Build the extension. * * @return The built {@link WithFlywaySchemaHistory}. */ public WithFlywaySchemaHistory build() { return new WithFlywaySchemaHistory(dataSourceExtension, List.copyOf(allVersions), tableName); } } /** * Internal Flyway JOOQ table. */ @VisibleForTesting @EqualsAndHashCode(callSuper = true) static final class FlywayTable extends TableImpl { private static final int VERSION_SIZE = 50; private static final int DESCRIPTION_SIZE = 200; private static final int TYPE_SIZE = 20; private static final int SCRIPT_SIZE = 1000; private static final int INSTALLED_BY_SIZE = 100; final TableField installedRank = createField(DSL.name("installed_rank"), SQLDataType.INTEGER, this, ""); final TableField version = createField(DSL.name("version"), SQLDataType.VARCHAR(VERSION_SIZE).nullable(false), this, ""); final TableField description = createField(DSL.name("description"), SQLDataType.VARCHAR(DESCRIPTION_SIZE), this, ""); final TableField type = createField(DSL.name("type"), SQLDataType.VARCHAR(TYPE_SIZE), this, ""); final TableField script = createField(DSL.name("script"), SQLDataType.VARCHAR(SCRIPT_SIZE), this, ""); final TableField checksum = createField(DSL.name("checksum"), SQLDataType.INTEGER, this, ""); final TableField installedBy = createField(DSL.name("installed_by"), SQLDataType.VARCHAR(INSTALLED_BY_SIZE), this, ""); final TableField installedOn = createField(DSL.name("installed_on"), SQLDataType.TIMESTAMP.precision(6), this, ""); final TableField executionTime = createField(DSL.name("execution_time"), SQLDataType.INTEGER, this, ""); final TableField success = createField(DSL.name("success"), SQLDataType.BOOLEAN, this, ""); private final List> allFields = List.of( installedRank, version, description, type, script, checksum, installedBy, installedOn, executionTime, success ); private final AtomicInteger currentRank = new AtomicInteger(0); FlywayTable(String tableName, String schema) { super(DSL.name(tableName), DSL.schema(DSL.name(schema))); } @Override public UniqueKey getPrimaryKey() { return Internal.createUniqueKey(this, DSL.name("flyway_pk"), installedRank); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy