From 80ac10e1c82fdf144f5cc21e03ed295b943fb7a4 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 15 Jun 2023 16:13:41 +0200 Subject: [PATCH] [jOOQ/jOOQ#9506] Added a History API draft --- jOOQ/src/main/java/org/jooq/File.java | 19 ++ jOOQ/src/main/java/org/jooq/Files.java | 13 + jOOQ/src/main/java/org/jooq/History.java | 86 ++++++ jOOQ/src/main/java/org/jooq/Migrations.java | 11 + .../main/java/org/jooq/impl/CommitImpl.java | 4 + .../java/org/jooq/impl/DefaultDSLContext.java | 5 +- .../main/java/org/jooq/impl/HistoryImpl.java | 279 ++++++++++++++++++ .../java/org/jooq/impl/MigrationImpl.java | 170 ++--------- .../java/org/jooq/impl/MigrationsImpl.java | 22 +- .../main/java/org/jooq/impl/VersionImpl.java | 32 +- 10 files changed, 466 insertions(+), 175 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/History.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/HistoryImpl.java diff --git a/jOOQ/src/main/java/org/jooq/File.java b/jOOQ/src/main/java/org/jooq/File.java index c90bba2cb3..a49fd7cc09 100644 --- a/jOOQ/src/main/java/org/jooq/File.java +++ b/jOOQ/src/main/java/org/jooq/File.java @@ -43,6 +43,9 @@ import org.jetbrains.annotations.ApiStatus.Experimental; /** * A source of migration content. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. * * @author Lukas Eder */ @@ -51,25 +54,41 @@ public interface File { /** * The path of the file within the repository. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ + @Experimental @NotNull String path(); /** * The name of the file. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ + @Experimental @NotNull String name(); /** * The file content. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ + @Experimental @Nullable String content(); /** * The file type. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ + @Experimental @NotNull ContentType type(); } diff --git a/jOOQ/src/main/java/org/jooq/Files.java b/jOOQ/src/main/java/org/jooq/Files.java index 69d452993b..27c43ae00f 100644 --- a/jOOQ/src/main/java/org/jooq/Files.java +++ b/jOOQ/src/main/java/org/jooq/Files.java @@ -38,24 +38,37 @@ package org.jooq; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.ApiStatus.Experimental; /** * A set of files that are in a specific order. *

* This type will help make sure that duplicate occurrences of the same file * (e.g. edits) are streamlined. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ +@Experimental public interface Files extends Iterable { /** * The from version from which this migration is done. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ @NotNull + @Experimental Version from(); /** * The to version to which this migration is done. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. */ @NotNull + @Experimental Version to(); } diff --git a/jOOQ/src/main/java/org/jooq/History.java b/jOOQ/src/main/java/org/jooq/History.java new file mode 100644 index 0000000000..ecd2c92981 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/History.java @@ -0,0 +1,86 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: https://www.jooq.org/legal/licensing + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import org.jooq.exception.DataMigrationVerificationException; + +import org.jetbrains.annotations.ApiStatus.Experimental; +import org.jetbrains.annotations.NotNull; + +/** + * The History of {@link Version} elements as installed by previous + * {@link Migrations}. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. + * + * @author Lukas Eder + */ +@Experimental +public interface History extends Iterable { + + /** + * The root {@link Version}. + *

+ * This corresponds to the {@link Configuration#commitProvider()}'s + * {@link Commits#root()} if migrations have been initialised on the + * configured database. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. + * + * @throws DataMigrationVerificationException If no root version is + * available (e.g. because no migration has happened yet). + */ + @NotNull + @Experimental + Version root() throws DataMigrationVerificationException; + + /** + * The currently installed {@link Version}. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. + * + * @throws DataMigrationVerificationException If no root version is + * available (e.g. because no migration has happened yet). + */ + @NotNull + @Experimental + Version current(); +} diff --git a/jOOQ/src/main/java/org/jooq/Migrations.java b/jOOQ/src/main/java/org/jooq/Migrations.java index 7469343124..f0dced4167 100644 --- a/jOOQ/src/main/java/org/jooq/Migrations.java +++ b/jOOQ/src/main/java/org/jooq/Migrations.java @@ -80,6 +80,17 @@ public interface Migrations { @NotNull Commits commits(); + /** + * Retrieve the {@link History} of previously installed {@link Version} + * objects from the database. + *

+ * This is EXPERIMENTAL functionality and subject to change in future jOOQ + * versions. + */ + @Experimental + @NotNull + History history(); + /** * Create a migration from the currently installed version to a new version. *

diff --git a/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java b/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java index ef66141fa6..cac7c3a43f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java @@ -423,6 +423,10 @@ final class CommitImpl extends AbstractNode implements Commit { files.clear(); } + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + @Override public int hashCode() { return id().hashCode(); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java index 0617665cdd..86a28b55e2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java @@ -175,6 +175,7 @@ import org.jooq.MergeKeyStep9; import org.jooq.MergeKeyStepN; import org.jooq.MergeUsingStep; import org.jooq.Meta; +import org.jooq.Migrations; import org.jooq.Name; import org.jooq.Param; import org.jooq.Parser; @@ -393,8 +394,8 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri } @Override - public org.jooq.Migrations migrations() { - return new MigrationsImpl(this); + public Migrations migrations() { + return new MigrationsImpl(configuration()); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/HistoryImpl.java b/jOOQ/src/main/java/org/jooq/impl/HistoryImpl.java new file mode 100644 index 0000000000..4d93ab9a23 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/HistoryImpl.java @@ -0,0 +1,279 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: https://www.jooq.org/legal/licensing + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static java.lang.Boolean.TRUE; +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableList; +import static org.jooq.impl.DSL.inline; +import static org.jooq.impl.DSL.name; +import static org.jooq.impl.DSL.schema; +import static org.jooq.impl.History.HISTORY; +import static org.jooq.impl.MigrationImpl.Status.SUCCESS; +import static org.jooq.impl.Tools.isEmpty; +import static org.jooq.tools.StringUtils.isBlank; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.jooq.Commit; +import org.jooq.Commits; +import org.jooq.Configuration; +import org.jooq.DSLContext; +import org.jooq.History; +import org.jooq.Schema; +import org.jooq.Version; +import org.jooq.conf.InterpreterSearchSchema; +import org.jooq.conf.MappedCatalog; +import org.jooq.conf.MappedSchema; +import org.jooq.conf.MigrationSchema; +import org.jooq.conf.RenderMapping; +import org.jooq.exception.DataAccessException; +import org.jooq.exception.DataMigrationVerificationException; + +import org.jetbrains.annotations.Nullable; + +/** + * @author Lukas Eder + */ +class HistoryImpl extends AbstractScope implements History { + + final DSLContext ctx; + final DSLContext historyCtx; + final Commits commits; + final List versions; + + HistoryImpl(Configuration configuration) { + super(configuration); + + this.ctx = configuration.dsl(); + this.historyCtx = initCtx(configuration, configuration.settings().getMigrationHistorySchema()).dsl(); + this.commits = configuration.commitProvider().provide(); + this.versions = initVersions(); + } + + @Override + public final Iterator iterator() { + return unmodifiableList(versions).iterator(); + } + + @Override + public final Version root() { + if (!isEmpty(versions)) + return versions.get(0); + else + throw new DataMigrationVerificationException("No versions are available"); + } + + @Override + public final Version current() { + if (!isEmpty(versions)) + return versions.get(versions.size() - 1); + else + throw new DataMigrationVerificationException("No versions are available"); + } + + final Set schemas() { + Set set = new LinkedHashSet<>(); + + for (MigrationSchema schema : configuration.settings().getMigrationSchemata()) + addSchema(set, schema); + + if (configuration.settings().getMigrationDefaultSchema() != null) { + addSchema(set, configuration.settings().getMigrationDefaultSchema()); + set.add(DSL.schema("")); + } + + return set; + } + + private final void addSchema(Set set, MigrationSchema schema) { + if (schema != null) + set.addAll(lookup(asList(schema(name(schema.getCatalog(), schema.getSchema()))))); + } + + final Collection lookup(List schemas) { + + // TODO: Refactor usages of getInterpreterSearchPath() + Collection result = schemas; + List searchPath = configuration().settings().getInterpreterSearchPath(); + + if (!searchPath.isEmpty()) { + result = new HashSet<>(); + Schema defaultSchema = schema(name(searchPath.get(0).getCatalog(), searchPath.get(0).getSchema())); + + for (Schema schema : schemas) + if (schema.getQualifiedName().empty()) + result.add(defaultSchema); + else + result.add(schema); + } + + return result; + } + + static final Configuration initCtx(Configuration configuration, MigrationSchema defaultSchema) { + if (defaultSchema != null) { + Configuration result = configuration.derive(); + + if (!isBlank(defaultSchema.getCatalog())) { + result.settings().withRenderMapping(new RenderMapping() + .withCatalogs(new MappedCatalog() + .withInput("") + .withOutput(defaultSchema.getCatalog()) + .withSchemata(new MappedSchema() + .withInput("") + .withOutput(defaultSchema.getSchema()) + ) + ) + ); + } + else if (!isBlank(defaultSchema.getSchema())) { + result.settings().withRenderMapping(new RenderMapping() + .withSchemata(new MappedSchema() + .withInput("") + .withOutput(defaultSchema.getSchema()) + ) + ); + } + + return result; + } + else + return configuration; + } + + @Nullable + final HistoryRecord currentHistoryRecord() { + return existsHistory() + ? historyCtx.selectFrom(HISTORY) + + // TODO: How to recover from failure? + .where(HISTORY.STATUS.eq(inline(SUCCESS))) + .orderBy(HISTORY.MIGRATED_AT.desc(), HISTORY.ID.desc()) + .limit(1) + .fetchOne() + : null; + } + + final boolean existsHistory() { + + // [#8301] Find a better way to test if our table already exists + try { + Configuration c = historyCtx + .configuration() + .derive(); + c.data("org.jooq.tools.LoggerListener.exception.mute", true); + c.dsl().fetchExists(HISTORY); + return true; + } + catch (DataAccessException ignore) {} + + return false; + } + + private final List initVersions() { + List result = new ArrayList<>(); + + if (existsHistory()) { + result.add(commits.root().version()); + + for (HistoryRecord r : historyCtx + .selectFrom(HISTORY) + .where(HISTORY.STATUS.eq(inline(SUCCESS))) + .orderBy(HISTORY.ID.asc()) + ) { + Commit commit = commits.get(r.getMigratedTo()); + + if (commit != null) + result.add(commit.version()); + else + throw new DataMigrationVerificationException("CommitProvider didn't provide version for ID: " + r.getMigratedTo()); + } + } + + return result; + } + + final void init() { + + // TODO: What to do when initialising jOOQ-migrations on an existing database? + // - Should there be init() commands that can be run explicitly by the user? + // - Will we reverse engineer the production Meta snapshot first? + if (!existsHistory()) { + + // TODO: [#9506] Make this schema creation vendor agnostic + // TODO: [#15225] This CREATE SCHEMA statement should never be necessary. + if (TRUE.equals(historyCtx.settings().isMigrationHistorySchemaCreateSchemaIfNotExists()) + && historyCtx.settings().getMigrationHistorySchema() != null + || TRUE.equals(historyCtx.settings().isMigrationSchemataCreateSchemaIfNotExists()) + && historyCtx.settings().getMigrationDefaultSchema() != null) + historyCtx.createSchemaIfNotExists("").execute(); + + historyCtx.meta(HISTORY).ddl().executeBatch(); + } + } + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public int hashCode() { + return versions.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HistoryImpl h) { + return versions.equals(h.versions); + } + + return false; + } + + @Override + public String toString() { + return "History [" + current() + "]"; + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java index a2a330ac0b..4c55889dd2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java @@ -39,26 +39,19 @@ package org.jooq.impl; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; -import static java.util.Arrays.asList; import static org.jooq.impl.DSL.createSchemaIfNotExists; import static org.jooq.impl.DSL.dropSchemaIfExists; import static org.jooq.impl.DSL.dropTableIfExists; -import static org.jooq.impl.DSL.inline; -import static org.jooq.impl.DSL.name; -import static org.jooq.impl.DSL.schema; import static org.jooq.impl.History.HISTORY; +import static org.jooq.impl.HistoryImpl.initCtx; import static org.jooq.impl.MigrationImpl.Status.FAILURE; import static org.jooq.impl.MigrationImpl.Status.MIGRATING; import static org.jooq.impl.MigrationImpl.Status.REVERTING; import static org.jooq.impl.MigrationImpl.Status.STARTING; import static org.jooq.impl.MigrationImpl.Status.SUCCESS; -import static org.jooq.tools.StringUtils.isBlank; import java.sql.Timestamp; -import java.util.Collection; import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; import org.jooq.Commit; @@ -66,7 +59,6 @@ import org.jooq.Commits; import org.jooq.Configuration; import org.jooq.Constants; import org.jooq.ContextTransactionalRunnable; -import org.jooq.DSLContext; import org.jooq.Files; import org.jooq.Meta; import org.jooq.Migration; @@ -75,11 +67,6 @@ import org.jooq.MigrationListener; import org.jooq.Queries; import org.jooq.Query; import org.jooq.Schema; -import org.jooq.conf.InterpreterSearchSchema; -import org.jooq.conf.MappedCatalog; -import org.jooq.conf.MappedSchema; -import org.jooq.conf.MigrationSchema; -import org.jooq.conf.RenderMapping; import org.jooq.exception.DataAccessException; import org.jooq.exception.DataMigrationException; import org.jooq.exception.DataMigrationVerificationException; @@ -92,7 +79,7 @@ import org.jooq.tools.StopWatch; final class MigrationImpl extends AbstractScope implements Migration { static final JooqLogger log = JooqLogger.getLogger(Migration.class); - final DSLContext historyCtx; + final HistoryImpl history; final Commit to; Commit from; Queries queries; @@ -105,38 +92,7 @@ final class MigrationImpl extends AbstractScope implements Migration { )); this.to = to; - this.historyCtx = initCtx(configuration(), configuration.settings().getMigrationHistorySchema()).dsl(); - } - - private static final Configuration initCtx(Configuration configuration, MigrationSchema defaultSchema) { - if (defaultSchema != null) { - Configuration result = configuration.derive(); - - if (!isBlank(defaultSchema.getCatalog())) { - result.settings().withRenderMapping(new RenderMapping() - .withCatalogs(new MappedCatalog() - .withInput("") - .withOutput(defaultSchema.getCatalog()) - .withSchemata(new MappedSchema() - .withInput("") - .withOutput(defaultSchema.getSchema()) - ) - ) - ); - } - else if (!isBlank(defaultSchema.getSchema())) { - result.settings().withRenderMapping(new RenderMapping() - .withSchemata(new MappedSchema() - .withInput("") - .withOutput(defaultSchema.getSchema()) - ) - ); - } - - return result; - } - else - return configuration; + this.history = new HistoryImpl(configuration()); } @Override @@ -177,7 +133,7 @@ final class MigrationImpl extends AbstractScope implements Migration { } private final void verify0(DefaultMigrationContext ctx) { - HistoryRecord currentRecord = currentHistoryRecord(); + HistoryRecord currentRecord = history.currentHistoryRecord(); if (currentRecord != null) { Commit currentCommit = commits().get(currentRecord.getMigratedTo()); @@ -195,39 +151,19 @@ final class MigrationImpl extends AbstractScope implements Migration { if (commits().get(commit.id()) == null) throw new DataMigrationVerificationException("Commit is not available from CommitProvider: " + commit.id()); - for (Schema schema : lookup(commit.meta().getSchemas())) + for (Schema schema : history.lookup(commit.meta().getSchemas())) if (!ctx.migratedSchemas().contains(schema)) throw new DataMigrationVerificationException("Schema is referenced from commit, but not configured for migration: " + schema); } - private final Collection lookup(List schemas) { - - // TODO: Refactor usages of getInterpreterSearchPath() - Collection result = schemas; - List searchPath = dsl().settings().getInterpreterSearchPath(); - - if (!searchPath.isEmpty()) { - result = new HashSet<>(); - Schema defaultSchema = schema(name(searchPath.get(0).getCatalog(), searchPath.get(0).getSchema())); - - for (Schema schema : schemas) - if (schema.getQualifiedName().empty()) - result.add(defaultSchema); - else - result.add(schema); - } - - return result; - } - private final Queries revertUntrackedQueries(Set includedSchemas) { Commit currentCommit = currentCommit(); Meta currentMeta = currentCommit.meta(); Meta existingMeta = dsl().meta().filterSchemas(includedSchemas::contains); Set expectedSchemas = new HashSet<>(); - expectedSchemas.addAll(lookup(from().meta().getSchemas())); - expectedSchemas.addAll(lookup(to().meta().getSchemas())); + expectedSchemas.addAll(history.lookup(from().meta().getSchemas())); + expectedSchemas.addAll(history.lookup(to().meta().getSchemas())); expectedSchemas.retainAll(includedSchemas); schemaLoop: @@ -258,8 +194,8 @@ final class MigrationImpl extends AbstractScope implements Migration { execute(ctx, listener, ctx.revertUntrackedQueries); } - private final DefaultMigrationContext migrationContext() { - Set schemas = schemas(); + final DefaultMigrationContext migrationContext() { + Set schemas = history.schemas(); return new DefaultMigrationContext( configuration(), @@ -271,25 +207,6 @@ final class MigrationImpl extends AbstractScope implements Migration { ); } - private final Set schemas() { - Set set = new LinkedHashSet<>(); - - for (MigrationSchema schema : configuration.settings().getMigrationSchemata()) - addSchema(set, schema); - - if (configuration.settings().getMigrationDefaultSchema() != null) { - addSchema(set, configuration.settings().getMigrationDefaultSchema()); - set.add(DSL.schema("")); - } - - return set; - } - - private final void addSchema(Set set, MigrationSchema schema) { - if (schema != null) - set.addAll(lookup(asList(schema(name(schema.getCatalog(), schema.getSchema()))))); - } - @Override public final void execute() { @@ -355,7 +272,7 @@ final class MigrationImpl extends AbstractScope implements Migration { } private final HistoryRecord createRecord(Status status) { - HistoryRecord record = historyCtx.newRecord(HISTORY); + HistoryRecord record = history.historyCtx.newRecord(HISTORY); record .setJooqVersion(Constants.VERSION) @@ -401,22 +318,7 @@ final class MigrationImpl extends AbstractScope implements Migration { * History. */ final void init() { - - // TODO: What to do when initialising jOOQ-migrations on an existing database? - // - Should there be init() commands that can be run explicitly by the user? - // - Will we reverse engineer the production Meta snapshot first? - if (!existsHistory()) { - - // TODO: [#9506] Make this schema creation vendor agnostic - // TODO: [#15225] This CREATE SCHEMA statement should never be necessary. - if (TRUE.equals(historyCtx.settings().isMigrationHistorySchemaCreateSchemaIfNotExists()) - && historyCtx.settings().getMigrationHistorySchema() != null - || TRUE.equals(historyCtx.settings().isMigrationSchemataCreateSchemaIfNotExists()) - && historyCtx.settings().getMigrationDefaultSchema() != null) - historyCtx.createSchemaIfNotExists("").execute(); - - historyCtx.meta(HISTORY).ddl().executeBatch(); - } + history.init(); MigrationContext ctx = migrationContext(); if (TRUE.equals(ctx.settings().isMigrationSchemataCreateSchemaIfNotExists())) @@ -424,36 +326,8 @@ final class MigrationImpl extends AbstractScope implements Migration { dsl().createSchemaIfNotExists(schema).execute(); } - private final boolean existsHistory() { - - // [#8301] Find a better way to test if our table already exists - try { - Configuration c = historyCtx - .configuration() - .derive(); - c.data("org.jooq.tools.LoggerListener.exception.mute", true); - c.dsl().fetchExists(HISTORY); - return true; - } - catch (DataAccessException ignore) {} - - return false; - } - - private final HistoryRecord currentHistoryRecord() { - return existsHistory() - ? historyCtx.selectFrom(HISTORY) - - // TODO: How to recover from failure? - .where(HISTORY.STATUS.eq(inline(SUCCESS))) - .orderBy(HISTORY.MIGRATED_AT.desc(), HISTORY.ID.desc()) - .limit(1) - .fetchOne() - : null; - } - final Commit currentCommit() { - HistoryRecord currentRecord = currentHistoryRecord(); + HistoryRecord currentRecord = history.currentHistoryRecord(); if (currentRecord == null) { Commit result = TRUE.equals(settings().isMigrationAutoBaseline()) ? to() : to().root(); @@ -486,6 +360,18 @@ final class MigrationImpl extends AbstractScope implements Migration { } } + enum Status { + STARTING, + REVERTING, + MIGRATING, + SUCCESS, + FAILURE + } + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -496,12 +382,4 @@ final class MigrationImpl extends AbstractScope implements Migration { return sb.toString(); } - - enum Status { - STARTING, - REVERTING, - MIGRATING, - SUCCESS, - FAILURE - } } diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationsImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationsImpl.java index 386412a1ad..b22af2de7c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MigrationsImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MigrationsImpl.java @@ -41,9 +41,10 @@ import static java.util.Collections.emptyList; import org.jooq.Commit; import org.jooq.Commits; +import org.jooq.Configuration; import org.jooq.ContentType; -import org.jooq.DSLContext; import org.jooq.File; +import org.jooq.History; import org.jooq.Migration; import org.jooq.Migrations; import org.jooq.Version; @@ -51,12 +52,10 @@ import org.jooq.Version; /** * @author Lukas Eder */ -final class MigrationsImpl implements Migrations { +final class MigrationsImpl extends AbstractScope implements Migrations { - final DSLContext ctx; - - MigrationsImpl(DSLContext ctx) { - this.ctx = ctx; + MigrationsImpl(Configuration configuration) { + super(configuration); } @Override @@ -64,18 +63,23 @@ final class MigrationsImpl implements Migrations { return new FileImpl(path, content, type); } + @Override + public final History history() { + return new HistoryImpl(configuration()); + } + @Override public final Version version(String id) { - return new VersionImpl(ctx, id); + return new VersionImpl(configuration(), id); } @Override public final Commits commits() { - return new CommitsImpl(ctx.configuration(), new CommitImpl(ctx.configuration(), "init", "init", null, emptyList(), emptyList())); + return new CommitsImpl(configuration(), new CommitImpl(configuration(), "init", "init", null, emptyList(), emptyList())); } @Override public final Migration migrateTo(Commit to) { - return new MigrationImpl(ctx.configuration(), to); + return new MigrationImpl(configuration(), to); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/VersionImpl.java b/jOOQ/src/main/java/org/jooq/impl/VersionImpl.java index bbcfdf3a83..1f28ab58a4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/VersionImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/VersionImpl.java @@ -40,7 +40,6 @@ package org.jooq.impl; import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableList; import static org.jooq.impl.DSL.createSchema; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.schema; @@ -51,12 +50,9 @@ import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import org.jooq.Configuration; import org.jooq.DSLContext; import org.jooq.Meta; import org.jooq.Queries; @@ -75,10 +71,10 @@ final class VersionImpl extends AbstractNode implements Version { final Meta meta; final List parents; - private VersionImpl(DSLContext ctx, String id, Meta meta, Version root, List parents) { + private VersionImpl(Configuration configuration, String id, Meta meta, Version root, List parents) { super(id, null, root); - this.ctx = ctx; + this.ctx = configuration.dsl(); this.meta = meta != null ? meta : init(ctx); this.parents = parents; } @@ -96,19 +92,19 @@ final class VersionImpl extends AbstractNode implements Version { return result; } - VersionImpl(DSLContext ctx, String id, Meta meta, Version root, Version parent, Queries queries) { - this(ctx, id, meta, root, Arrays.asList(new Parent((VersionImpl) parent, queries))); + VersionImpl(Configuration configuration, String id, Meta meta, Version root, Version parent, Queries queries) { + this(configuration, id, meta, root, Arrays.asList(new Parent((VersionImpl) parent, queries))); } - VersionImpl(DSLContext ctx, String id, Meta meta, Version root, Version[] parents) { - this(ctx, id, meta, root, wrap(parents)); + VersionImpl(Configuration configuration, String id, Meta meta, Version root, Version[] parents) { + this(configuration, id, meta, root, wrap(parents)); } /** * Create the root {@link Version}. */ - VersionImpl(DSLContext ctx, String id) { - this(ctx, id, null, null, asList()); + VersionImpl(Configuration configuration, String id) { + this(configuration, id, null, null, asList()); } private static List wrap(Version[] parents) { @@ -152,7 +148,7 @@ final class VersionImpl extends AbstractNode implements Version { @Override public final Version apply(String newId, Queries migration) { - return new VersionImpl(ctx, newId, meta().apply(migration), root, this, migration); + return new VersionImpl(ctx.configuration(), newId, meta().apply(migration), root, this, migration); } @Override @@ -181,7 +177,7 @@ final class VersionImpl extends AbstractNode implements Version { if (list == null) list = new ArrayList<>(); - list.add(new Parent(new VersionImpl(ctx, parent.version.id(), parent.version.meta, root, emptyList()), parent.queries)); + list.add(new Parent(new VersionImpl(ctx.configuration(), parent.version.id(), parent.version.meta, root, emptyList()), parent.queries)); } else { VersionImpl p = parent.version.subgraphTo(ancestor); @@ -195,7 +191,7 @@ final class VersionImpl extends AbstractNode implements Version { } } - return list == null ? null : new VersionImpl(ctx, id(), meta, root, list); + return list == null ? null : new VersionImpl(ctx.configuration(), id(), meta, root, list); } private final Queries migrateTo(VersionImpl target, Queries result) { @@ -230,13 +226,13 @@ final class VersionImpl extends AbstractNode implements Version { @Override public final Version commit(String newId, Meta newMeta) { - return new VersionImpl(ctx, newId, newMeta, root, new Version[] { this }); + return new VersionImpl(ctx.configuration(), newId, newMeta, root, new Version[] { this }); } @Override public final Version merge(String newId, Version with) { Meta m = commonAncestor(with).meta(); - return new VersionImpl(ctx, newId, m.apply(m.migrateTo(meta()).concat(m.migrateTo(with.meta()))), root, new Version[] { this, with }); + return new VersionImpl(ctx.configuration(), newId, m.apply(m.migrateTo(meta()).concat(m.migrateTo(with.meta()))), root, new Version[] { this, with }); } @Override