[jOOQ/jOOQ#9506] More work on Migrations API:
- Handling of default schema in MigrationImpl::revertUntrackedQueries - Use Settings.migrationHistorySchema in revertUntrackedQueries - Improve logic to filter out history table from revertUntrackedQueries - Set migration default schema as interpreter search path in History - Suppress exceptions caused by history record re-insertion in case of DataMigrationRedoLogException - VersionImpl should apply CREATE SCHEMA IF NOT EXISTS to on init - Remove weird initialisation of VersionImpl.meta with interpreter search path - Implement DefaultMigrationContext::toString - Automatically set interpreter search path in Maven plugin - GitCommitProvider should use same content type subdirs (in plural) - Add commitProvider property to Maven plugin - Upgrade jgit - Allow for configuring a basedir within the GitConfiguration#repository
This commit is contained in:
parent
f086212738
commit
1dd1205673
@ -37,9 +37,6 @@
|
||||
*/
|
||||
package org.jooq.migrations.maven;
|
||||
|
||||
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
|
||||
import static org.apache.maven.plugins.annotations.ResolutionScope.TEST;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jooq.CommitProvider;
|
||||
@ -47,9 +44,9 @@ import org.jooq.Commits;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Migration;
|
||||
import org.jooq.Migrations;
|
||||
import org.jooq.impl.DefaultCommitProvider;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
|
||||
/**
|
||||
* A base class for {@link MigrateMojo},
|
||||
@ -63,21 +60,18 @@ public abstract class AbstractMigrateMojo extends AbstractMigrationsMojo {
|
||||
if (directory == null)
|
||||
throw new MojoExecutionException("Directory was not provided");
|
||||
|
||||
Migrations migrations = configuration.dsl().migrations();
|
||||
Commits commits = migrations.commits();
|
||||
CommitProvider cp = configuration.commitProvider();
|
||||
if (cp instanceof DefaultCommitProvider) {
|
||||
Migrations migrations = configuration.dsl().migrations();
|
||||
Commits commits = migrations.commits();
|
||||
commits.load(file(directory));
|
||||
}
|
||||
|
||||
// [#9506] TODO: Support loading directories recursively
|
||||
// [#9506] TODO: Support loading **/*.sql style paths
|
||||
// [#9506] TODO: Support relative paths, absolute paths, etc.
|
||||
commits.load(file(directory));
|
||||
|
||||
// [#9506] TODO: Having to use this CommitsProvider "trick" isn't really
|
||||
// user friendly. There must be a better way
|
||||
Migration migration = configuration
|
||||
.derive((CommitProvider) () -> commits)
|
||||
.derive(cp)
|
||||
.dsl()
|
||||
.migrations()
|
||||
.migrateTo(commits.latest());
|
||||
.migrateTo(cp.provide().latest());
|
||||
|
||||
if (getLog().isInfoEnabled())
|
||||
getLog().info(
|
||||
|
||||
@ -46,9 +46,12 @@ import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.CloseableDSLContext;
|
||||
import org.jooq.CommitProvider;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.conf.InterpreterSearchSchema;
|
||||
import org.jooq.conf.MigrationSchema;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.DefaultCommitProvider;
|
||||
import org.jooq.tools.ClassUtils;
|
||||
import org.jooq.tools.jdbc.JDBCUtils;
|
||||
|
||||
@ -146,6 +149,12 @@ abstract class AbstractMigrationsMojo extends AbstractMojo {
|
||||
@Parameter(property = "jooq.migrate.historySchemaCreateSchemaIfNotExists")
|
||||
boolean historySchemaCreateSchemaIfNotExists;
|
||||
|
||||
/**
|
||||
* The {@link CommitProvider} implementation, defaulting to {@link DefaultCommitProvider}.
|
||||
*/
|
||||
@Parameter(property = "jooq.migrate.commitProvider")
|
||||
String commitProvider;
|
||||
|
||||
@Override
|
||||
public final void execute() throws MojoExecutionException {
|
||||
if (skip) {
|
||||
@ -174,13 +183,29 @@ abstract class AbstractMigrationsMojo extends AbstractMojo {
|
||||
|
||||
// Initialise Settings
|
||||
// ---------------------------------------------------------------------
|
||||
// TODO [#9506]: What are accepted constructor signatures?
|
||||
if (commitProvider != null)
|
||||
ctx.configuration().set((CommitProvider) ClassUtils
|
||||
.loadClass(commitProvider)
|
||||
.getConstructor(Configuration.class)
|
||||
.newInstance(ctx.configuration())
|
||||
);
|
||||
|
||||
ctx.settings().getMigrationSchemata().addAll(schemata);
|
||||
|
||||
if (defaultCatalog != null || defaultSchema != null)
|
||||
ctx.settings().setMigrationDefaultSchema(new MigrationSchema()
|
||||
.withCatalog(defaultIfNull(defaultCatalog, ""))
|
||||
.withSchema(defaultIfNull(defaultSchema, ""))
|
||||
);
|
||||
if (defaultCatalog != null || defaultSchema != null) {
|
||||
ctx.settings()
|
||||
.withMigrationDefaultSchema(new MigrationSchema()
|
||||
.withCatalog(defaultIfNull(defaultCatalog, ""))
|
||||
.withSchema(defaultIfNull(defaultSchema, ""))
|
||||
)
|
||||
|
||||
// [#9506] TODO: This should be automatic, even for programmatic usage
|
||||
.withInterpreterSearchPath(new InterpreterSearchSchema()
|
||||
.withCatalog(defaultIfNull(defaultCatalog, ""))
|
||||
.withSchema(defaultIfNull(defaultSchema, ""))
|
||||
);
|
||||
}
|
||||
|
||||
if (historyCatalog != null || historySchema != null)
|
||||
ctx.settings().setMigrationHistorySchema(new MigrationSchema()
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>6.6.1.202309021850-r</version>
|
||||
<version>7.0.0.202409031743-r</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -65,6 +65,7 @@ import org.jooq.File;
|
||||
import org.jooq.FilePattern;
|
||||
import org.jooq.Migrations;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.Status;
|
||||
@ -81,7 +82,6 @@ import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTag;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.eclipse.jgit.util.io.DisabledOutputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A {@link CommitProvider} that produces versions from a git repository.
|
||||
@ -98,12 +98,25 @@ public final class GitCommitProvider implements CommitProvider {
|
||||
private final FilePattern incrementFilePattern;
|
||||
private final FilePattern schemaFilePattern;
|
||||
|
||||
public GitCommitProvider(Configuration configuration) {
|
||||
this(configuration, new GitConfiguration());
|
||||
}
|
||||
|
||||
public GitCommitProvider(Configuration configuration, GitConfiguration git) {
|
||||
this.dsl = configuration.dsl();
|
||||
this.migrations = dsl.migrations();
|
||||
this.git = git;
|
||||
this.incrementFilePattern = new FilePattern().pattern(git.incrementFilePattern());
|
||||
this.schemaFilePattern = new FilePattern().pattern(git.schemaFilePattern());
|
||||
this.incrementFilePattern = new FilePattern().pattern(combine(git.basedir(), git.incrementFilePattern()));
|
||||
this.schemaFilePattern = new FilePattern().pattern(combine(git.basedir(), git.schemaFilePattern()));
|
||||
}
|
||||
|
||||
private static final String combine(String basedir, String pattern) {
|
||||
if (StringUtils.isEmpty(basedir))
|
||||
return pattern;
|
||||
else if (basedir.endsWith("/"))
|
||||
return basedir + pattern;
|
||||
else
|
||||
return basedir + "/" + pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,6 +128,9 @@ public final class GitCommitProvider implements CommitProvider {
|
||||
Repository r = g.getRepository();
|
||||
ObjectReader reader = r.newObjectReader()
|
||||
) {
|
||||
// Prevent a "close() called when useCnt is already zero" warning
|
||||
r.incrementOpen();
|
||||
|
||||
List<RevCommit> revCommits = new ArrayList<>();
|
||||
Map<String, List<RevTag>> tags = new HashMap<>();
|
||||
RevCommit last = null;
|
||||
@ -311,24 +327,34 @@ public final class GitCommitProvider implements CommitProvider {
|
||||
treeWalk.setRecursive(false);
|
||||
|
||||
while (treeWalk.next()) {
|
||||
if (treeWalk.isSubtree()) {
|
||||
String path = treeWalk.getPathString();
|
||||
|
||||
if (treeWalk.isSubtree() && include(path)) {
|
||||
treeWalk.enterSubtree();
|
||||
}
|
||||
else {
|
||||
ContentType contentType = contentType(treeWalk.getPathString());
|
||||
ContentType contentType = contentType(path);
|
||||
|
||||
if (contentType != null)
|
||||
if (contentType != null) {
|
||||
files.add(migrations.file(
|
||||
treeWalk.getPathString(),
|
||||
read(repository, revCommit, treeWalk.getPathString()),
|
||||
path,
|
||||
read(repository, revCommit, path),
|
||||
contentType
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private final boolean include(String path) {
|
||||
|
||||
// [#9506] TODO: resolve . and ..
|
||||
return git.basedir().startsWith(path)
|
||||
|| path.startsWith(git.basedir());
|
||||
}
|
||||
|
||||
private final String read(Repository repository, RevCommit commit, String path) throws IOException {
|
||||
try (TreeWalk treeWalk = TreeWalk.forPath(repository, path, commit.getTree())) {
|
||||
ObjectId blobId = treeWalk.getObjectId(0);
|
||||
|
||||
@ -40,11 +40,6 @@ package org.jooq.migrations.jgit;
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jooq.Commit;
|
||||
import org.jooq.tools.StringUtils;
|
||||
@ -58,6 +53,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class GitConfiguration {
|
||||
|
||||
private final File repository;
|
||||
private final String basedir;
|
||||
private final String schemaFilePattern;
|
||||
private final String incrementFilePattern;
|
||||
private final String scriptFilePattern;
|
||||
@ -71,12 +67,14 @@ public class GitConfiguration {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private GitConfiguration(
|
||||
File repository,
|
||||
String basedir,
|
||||
String schemaFilePattern,
|
||||
String incrementFilePattern,
|
||||
String scriptFilePattern,
|
||||
@ -84,10 +82,11 @@ public class GitConfiguration {
|
||||
boolean includeUncommitted
|
||||
) {
|
||||
this.repository = repository != null ? repository : new File(".");
|
||||
this.schemaFilePattern = defaultIfNull(schemaFilePattern, "migrations/schema/**");
|
||||
this.incrementFilePattern = defaultIfNull(incrementFilePattern, "migrations/increment/**");
|
||||
this.scriptFilePattern = defaultIfNull(scriptFilePattern, "migrations/script/**");
|
||||
this.snapshotFilePattern = defaultIfNull(snapshotFilePattern, "migrations/snapshot/**");
|
||||
this.basedir = basedir != null ? basedir : "src/main/resources";
|
||||
this.schemaFilePattern = defaultIfNull(schemaFilePattern, "migrations/schemas/**");
|
||||
this.incrementFilePattern = defaultIfNull(incrementFilePattern, "migrations/increments/**");
|
||||
this.scriptFilePattern = defaultIfNull(scriptFilePattern, "migrations/scripts/**");
|
||||
this.snapshotFilePattern = defaultIfNull(snapshotFilePattern, "migrations/snapshots/**");
|
||||
this.includeUncommitted = includeUncommitted;
|
||||
}
|
||||
|
||||
@ -98,6 +97,7 @@ public class GitConfiguration {
|
||||
public final GitConfiguration repository(File newRepository) {
|
||||
return new GitConfiguration(
|
||||
newRepository,
|
||||
basedir,
|
||||
schemaFilePattern,
|
||||
incrementFilePattern,
|
||||
scriptFilePattern,
|
||||
@ -114,6 +114,30 @@ public class GitConfiguration {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base directory of the migration scripts within the {@link #repository()}.
|
||||
*/
|
||||
@NotNull
|
||||
public final GitConfiguration basedir(String newBasedir) {
|
||||
return new GitConfiguration(
|
||||
repository,
|
||||
newBasedir,
|
||||
schemaFilePattern,
|
||||
incrementFilePattern,
|
||||
scriptFilePattern,
|
||||
snapshotFilePattern,
|
||||
includeUncommitted
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The base directory of the migration scripts within the {@link #repository()}.
|
||||
*/
|
||||
@NotNull
|
||||
public final String basedir() {
|
||||
return basedir;
|
||||
}
|
||||
|
||||
/**
|
||||
* The patterns of files in the repository to be searched for schema
|
||||
* definition files.
|
||||
@ -122,6 +146,7 @@ public class GitConfiguration {
|
||||
public final GitConfiguration schemaFilePattern(String newSchemaFilePattern) {
|
||||
return new GitConfiguration(
|
||||
repository,
|
||||
basedir,
|
||||
newSchemaFilePattern,
|
||||
incrementFilePattern,
|
||||
scriptFilePattern,
|
||||
@ -147,6 +172,7 @@ public class GitConfiguration {
|
||||
public final GitConfiguration incrementFilePattern(String newIncrementFilePattern) {
|
||||
return new GitConfiguration(
|
||||
repository,
|
||||
basedir,
|
||||
schemaFilePattern,
|
||||
newIncrementFilePattern,
|
||||
scriptFilePattern,
|
||||
@ -172,6 +198,7 @@ public class GitConfiguration {
|
||||
public final GitConfiguration includeUncommitted(boolean newIncludeUncommitted) {
|
||||
return new GitConfiguration(
|
||||
repository,
|
||||
basedir,
|
||||
schemaFilePattern,
|
||||
incrementFilePattern,
|
||||
scriptFilePattern,
|
||||
|
||||
@ -122,4 +122,17 @@ final class DefaultMigrationContext extends AbstractScope implements MigrationCo
|
||||
final void query(Query q) {
|
||||
this.query = q;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(
|
||||
"MigrationContext for migration from: " + migrationFrom + " to " + migrationTo + "\n"
|
||||
+ "Migration queries:\n" + migrationQueries
|
||||
+ "Revert untracked queries:\n" + revertUntrackedQueries
|
||||
);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ import org.jooq.UniqueKey;
|
||||
/**
|
||||
* The migration history of jOOQ Migrations.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
class History extends TableImpl<HistoryRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -64,6 +64,11 @@ class History extends TableImpl<HistoryRecord> {
|
||||
*/
|
||||
final TableField<HistoryRecord, String> MIGRATED_TO = createField(DSL.name("MIGRATED_TO"), SQLDataType.VARCHAR(255).nullable(false), this, "The current database version ID.");
|
||||
|
||||
/**
|
||||
* The column <code>JOOQ_MIGRATION_HISTORY.MIGRATED_TO_MESSAGE</code>.
|
||||
*/
|
||||
final TableField<HistoryRecord, String> MIGRATED_TO_MESSAGE = createField(DSL.name("MIGRATED_TO_MESSAGE"), SQLDataType.CLOB.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>JOOQ_MIGRATION_HISTORY.MIGRATED_TO_TAGS</code>. The
|
||||
* current database version tags, if any, in JSON array format.
|
||||
|
||||
@ -139,7 +139,7 @@ class HistoryImpl extends AbstractScope implements History {
|
||||
|
||||
private final void addSchema(Set<Schema> set, MigrationSchema schema) {
|
||||
if (schema != null)
|
||||
set.addAll(lookup(asList(schema(name(schema.getCatalog(), schema.getSchema())))));
|
||||
set.addAll(lookup(asList(MigrationImpl.schema(schema))));
|
||||
}
|
||||
|
||||
final Collection<Schema> lookup(List<Schema> schemas) {
|
||||
@ -187,6 +187,11 @@ class HistoryImpl extends AbstractScope implements History {
|
||||
);
|
||||
}
|
||||
|
||||
result.settings().withInterpreterSearchPath(new InterpreterSearchSchema()
|
||||
.withCatalog(defaultSchema.getCatalog())
|
||||
.withSchema(defaultSchema.getSchema())
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
|
||||
@ -12,7 +12,7 @@ import org.jooq.Record1;
|
||||
/**
|
||||
* The migration history of jOOQ Migrations.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -85,12 +85,27 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
return (String) get(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>JOOQ_MIGRATION_HISTORY.MIGRATED_TO_MESSAGE</code>.
|
||||
*/
|
||||
HistoryRecord setMigratedToMessage(String value) {
|
||||
set(4, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>JOOQ_MIGRATION_HISTORY.MIGRATED_TO_MESSAGE</code>.
|
||||
*/
|
||||
String getMigratedToMessage() {
|
||||
return (String) get(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>JOOQ_MIGRATION_HISTORY.MIGRATED_TO_TAGS</code>. The
|
||||
* current database version tags, if any, in JSON array format.
|
||||
*/
|
||||
HistoryRecord setMigratedToTags(String value) {
|
||||
set(4, value);
|
||||
set(5, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -99,7 +114,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* current database version tags, if any, in JSON array format.
|
||||
*/
|
||||
String getMigratedToTags() {
|
||||
return (String) get(4);
|
||||
return (String) get(5);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +122,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* in milliseconds it took to migrate to this database version.
|
||||
*/
|
||||
HistoryRecord setMigrationTime(Long value) {
|
||||
set(5, value);
|
||||
set(6, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -116,7 +131,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* in milliseconds it took to migrate to this database version.
|
||||
*/
|
||||
Long getMigrationTime() {
|
||||
return (Long) get(5);
|
||||
return (Long) get(6);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +139,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* version used to migrate to this database version.
|
||||
*/
|
||||
HistoryRecord setJooqVersion(String value) {
|
||||
set(6, value);
|
||||
set(7, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -133,7 +148,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* version used to migrate to this database version.
|
||||
*/
|
||||
String getJooqVersion() {
|
||||
return (String) get(6);
|
||||
return (String) get(7);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,7 +156,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* that were run to install this database version.
|
||||
*/
|
||||
HistoryRecord setSql(String value) {
|
||||
set(7, value);
|
||||
set(8, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -150,7 +165,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* that were run to install this database version.
|
||||
*/
|
||||
String getSql() {
|
||||
return (String) get(7);
|
||||
return (String) get(8);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,7 +173,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* SQL statements that were run to install this database version.
|
||||
*/
|
||||
HistoryRecord setSqlCount(Integer value) {
|
||||
set(8, value);
|
||||
set(9, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -167,7 +182,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* SQL statements that were run to install this database version.
|
||||
*/
|
||||
Integer getSqlCount() {
|
||||
return (Integer) get(8);
|
||||
return (Integer) get(9);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -175,7 +190,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* version installation status.
|
||||
*/
|
||||
HistoryRecord setStatus(HistoryStatus value) {
|
||||
set(9, value);
|
||||
set(10, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -184,7 +199,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* version installation status.
|
||||
*/
|
||||
HistoryStatus getStatus() {
|
||||
return (HistoryStatus) get(9);
|
||||
return (HistoryStatus) get(10);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,7 +207,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* or error message explaining the status.
|
||||
*/
|
||||
HistoryRecord setStatusMessage(String value) {
|
||||
set(10, value);
|
||||
set(11, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -201,7 +216,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* or error message explaining the status.
|
||||
*/
|
||||
String getStatusMessage() {
|
||||
return (String) get(10);
|
||||
return (String) get(11);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,7 +224,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* resolution, if any.
|
||||
*/
|
||||
HistoryRecord setResolution(HistoryResolution value) {
|
||||
set(11, value);
|
||||
set(12, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -218,7 +233,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* resolution, if any.
|
||||
*/
|
||||
HistoryResolution getResolution() {
|
||||
return (HistoryResolution) get(11);
|
||||
return (HistoryResolution) get(12);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,7 +241,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* info or error message explaining the resolution.
|
||||
*/
|
||||
HistoryRecord setResolutionMessage(String value) {
|
||||
set(12, value);
|
||||
set(13, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -235,7 +250,7 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
* info or error message explaining the resolution.
|
||||
*/
|
||||
String getResolutionMessage() {
|
||||
return (String) get(12);
|
||||
return (String) get(13);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -261,13 +276,14 @@ class HistoryRecord extends UpdatableRecordImpl<HistoryRecord> {
|
||||
/**
|
||||
* Create a detached, initialised HistoryRecord
|
||||
*/
|
||||
HistoryRecord(Integer id, Timestamp migratedAt, String migratedFrom, String migratedTo, String migratedToTags, Long migrationTime, String jooqVersion, String sql, Integer sqlCount, HistoryStatus status, String statusMessage, HistoryResolution resolution, String resolutionMessage) {
|
||||
HistoryRecord(Integer id, Timestamp migratedAt, String migratedFrom, String migratedTo, String migratedToMessage, String migratedToTags, Long migrationTime, String jooqVersion, String sql, Integer sqlCount, HistoryStatus status, String statusMessage, HistoryResolution resolution, String resolutionMessage) {
|
||||
super(History.HISTORY);
|
||||
|
||||
setId(id);
|
||||
setMigratedAt(migratedAt);
|
||||
setMigratedFrom(migratedFrom);
|
||||
setMigratedTo(migratedTo);
|
||||
setMigratedToMessage(migratedToMessage);
|
||||
setMigratedToTags(migratedToTags);
|
||||
setMigrationTime(migrationTime);
|
||||
setJooqVersion(jooqVersion);
|
||||
|
||||
@ -12,7 +12,7 @@ import org.jooq.Schema;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public enum HistoryResolution implements EnumType {
|
||||
|
||||
OPEN("OPEN"),
|
||||
|
||||
@ -12,7 +12,7 @@ import org.jooq.Schema;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public enum HistoryStatus implements EnumType {
|
||||
|
||||
STARTING("STARTING"),
|
||||
|
||||
@ -39,9 +39,12 @@ package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.function.Predicate.not;
|
||||
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.name;
|
||||
import static org.jooq.impl.DSL.table;
|
||||
import static org.jooq.impl.History.HISTORY;
|
||||
import static org.jooq.impl.HistoryImpl.initCtx;
|
||||
import static org.jooq.impl.HistoryResolution.OPEN;
|
||||
@ -50,6 +53,7 @@ import static org.jooq.impl.HistoryStatus.MIGRATING;
|
||||
import static org.jooq.impl.HistoryStatus.REVERTING;
|
||||
import static org.jooq.impl.HistoryStatus.STARTING;
|
||||
import static org.jooq.impl.HistoryStatus.SUCCESS;
|
||||
import static org.jooq.impl.SchemaImpl.DEFAULT_SCHEMA;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@ -57,6 +61,7 @@ import java.io.StringWriter;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jooq.Commit;
|
||||
import org.jooq.Commits;
|
||||
@ -71,7 +76,11 @@ import org.jooq.MigrationListener;
|
||||
import org.jooq.Queries;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.Tag;
|
||||
import org.jooq.conf.InterpreterSearchSchema;
|
||||
import org.jooq.conf.MigrationSchema;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.DataMigrationException;
|
||||
import org.jooq.exception.DataMigrationVerificationException;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
@ -101,6 +110,10 @@ final class MigrationImpl extends AbstractScope implements Migration {
|
||||
this.history = new HistoryImpl(configuration());
|
||||
}
|
||||
|
||||
static final Schema schema(MigrationSchema schema) {
|
||||
return new SchemaImpl(name(schema.getCatalog(), schema.getSchema()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Commit from() {
|
||||
if (from == null)
|
||||
@ -184,23 +197,39 @@ final class MigrationImpl extends AbstractScope implements Migration {
|
||||
}
|
||||
|
||||
private final Queries revertUntrackedQueries(Set<Schema> includedSchemas) {
|
||||
MigrationSchema hs = settings().getMigrationHistorySchema();
|
||||
MigrationSchema ds = settings().getMigrationDefaultSchema();
|
||||
|
||||
Set<Table<?>> historyTables = new HashSet<>();
|
||||
|
||||
if (hs != null || ds != null)
|
||||
historyTables.add(table(schema(hs != null ? hs : ds).getQualifiedName().append(HISTORY.getUnqualifiedName())));
|
||||
else
|
||||
historyTables.addAll(map(includedSchemas, s -> table(s.getQualifiedName().append(HISTORY.getUnqualifiedName()))));
|
||||
|
||||
Commit currentCommit = currentCommit();
|
||||
Meta currentMeta = currentCommit.meta();
|
||||
Meta existingMeta = dsl().meta().filterSchemas(includedSchemas::contains);
|
||||
Meta existingMeta = dsl().meta()
|
||||
.filterSchemas(includedSchemas::contains)
|
||||
.filterTables(not(historyTables::contains));
|
||||
|
||||
Set<Schema> expectedSchemas = new HashSet<>();
|
||||
expectedSchemas.addAll(history.lookup(from().meta().getSchemas()));
|
||||
expectedSchemas.addAll(history.lookup(to().meta().getSchemas()));
|
||||
expectedSchemas.retainAll(includedSchemas);
|
||||
|
||||
if (ds != null) {
|
||||
Schema d = DEFAULT_SCHEMA.get();
|
||||
|
||||
if (expectedSchemas.contains(d) && includedSchemas.contains(d))
|
||||
expectedSchemas.add(schema(ds));
|
||||
}
|
||||
|
||||
schemaLoop:
|
||||
for (Schema schema : existingMeta.getSchemas()) {
|
||||
if (!includedSchemas.contains(schema))
|
||||
continue schemaLoop;
|
||||
|
||||
// TODO Why is this qualification necessary?
|
||||
existingMeta = existingMeta.apply(dropTableIfExists(schema.getQualifiedName().append(HISTORY.getUnqualifiedName())).cascade());
|
||||
|
||||
if (!expectedSchemas.contains(schema))
|
||||
existingMeta = existingMeta.apply(dropSchemaIfExists(schema).cascade());
|
||||
else
|
||||
@ -347,6 +376,7 @@ final class MigrationImpl extends AbstractScope implements Migration {
|
||||
.setMigratedAt(new Timestamp(dsl().configuration().clock().instant().toEpochMilli()))
|
||||
.setMigratedFrom(from().id())
|
||||
.setMigratedTo(to().id())
|
||||
.setMigratedToMessage(to().message())
|
||||
.setMigratedToTags(new JSONArray(map(to().tags(), Tag::id)).toString())
|
||||
.setMigrationTime(0L)
|
||||
.setSql(queries().toString())
|
||||
@ -426,13 +456,18 @@ final class MigrationImpl extends AbstractScope implements Migration {
|
||||
dsl().transaction(runnable);
|
||||
}
|
||||
catch (DataMigrationRedoLogException e) {
|
||||
try {
|
||||
|
||||
// [#9506] Make sure history record is re-created in case it was rolled back.
|
||||
HistoryRecord record = history.currentHistoryRecord(false);
|
||||
// [#9506] Make sure history record is re-created in case it was rolled back.
|
||||
HistoryRecord record = history.currentHistoryRecord(false);
|
||||
|
||||
if (record == null || !StringUtils.equals(e.record.getId(), record.getId())) {
|
||||
e.record.touched(true);
|
||||
e.record.insert();
|
||||
if (record == null || !StringUtils.equals(e.record.getId(), record.getId())) {
|
||||
e.record.touched(true);
|
||||
e.record.insert();
|
||||
}
|
||||
}
|
||||
catch (DataAccessException s) {
|
||||
e.addSuppressed(s);
|
||||
}
|
||||
|
||||
if (e.getCause() instanceof DataMigrationException r)
|
||||
|
||||
@ -41,8 +41,7 @@ import static java.lang.Boolean.TRUE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.jooq.impl.DSL.createSchema;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DSL.schema;
|
||||
import static org.jooq.impl.DSL.createSchemaIfNotExists;
|
||||
import static org.jooq.impl.Tools.anyMatch;
|
||||
import static org.jooq.impl.Tools.map;
|
||||
|
||||
@ -60,6 +59,7 @@ import org.jooq.Query;
|
||||
import org.jooq.Source;
|
||||
import org.jooq.Version;
|
||||
import org.jooq.conf.InterpreterSearchSchema;
|
||||
import org.jooq.conf.MigrationSchema;
|
||||
import org.jooq.exception.DataDefinitionException;
|
||||
|
||||
/**
|
||||
@ -82,12 +82,9 @@ final class VersionImpl extends AbstractNode<Version> implements Version {
|
||||
private static final Meta init(DSLContext ctx) {
|
||||
Meta result = ctx.meta("");
|
||||
|
||||
// TODO: Instead of reusing interpreter search path, we should have some dedicated
|
||||
// configuration for this.
|
||||
// TODO: Should this be moved in DSLContext.meta()?
|
||||
List<InterpreterSearchSchema> searchPath = ctx.settings().getInterpreterSearchPath();
|
||||
for (InterpreterSearchSchema schema : searchPath)
|
||||
result = result.apply(createSchema(schema(name(schema.getCatalog(), schema.getSchema()))));
|
||||
MigrationSchema ds = ctx.settings().getMigrationDefaultSchema();
|
||||
if (ds != null)
|
||||
result = result.apply(createSchemaIfNotExists(MigrationImpl.schema(ds)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
CREATE TABLE jooq_migration_history (
|
||||
id BIGINT NOT NULL IDENTITY,
|
||||
migrated_at TIMESTAMP NOT NULL,
|
||||
migrated_from VARCHAR(255) NOT NULL,
|
||||
migrated_to VARCHAR(255) NOT NULL,
|
||||
migrated_to_tags CLOB NOT NULL,
|
||||
migration_time BIGINT NULL,
|
||||
jooq_version VARCHAR(50) NOT NULL,
|
||||
sql CLOB NULL,
|
||||
sql_count INT NOT NULL,
|
||||
status VARCHAR(10) NOT NULL,
|
||||
status_message CLOB NULL,
|
||||
resolution VARCHAR(10) NULL,
|
||||
resolution_message CLOB NULL,
|
||||
id BIGINT NOT NULL IDENTITY,
|
||||
migrated_at TIMESTAMP NOT NULL,
|
||||
migrated_from VARCHAR(255) NOT NULL,
|
||||
migrated_to VARCHAR(255) NOT NULL,
|
||||
migrated_to_message CLOB NOT NULL,
|
||||
migrated_to_tags CLOB NOT NULL,
|
||||
migration_time BIGINT NULL,
|
||||
jooq_version VARCHAR(50) NOT NULL,
|
||||
sql CLOB NULL,
|
||||
sql_count INT NOT NULL,
|
||||
status VARCHAR(10) NOT NULL,
|
||||
status_message CLOB NULL,
|
||||
resolution VARCHAR(10) NULL,
|
||||
resolution_message CLOB NULL,
|
||||
|
||||
CONSTRAINT jooq_migr_hist_pk PRIMARY KEY (id),
|
||||
CONSTRAINT jooq_migr_hist_chk1 CHECK (status IN ('STARTING', 'REVERTING', 'MIGRATING', 'SUCCESS', 'FAILURE')),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user