Merge pull request #1635 from jamesagnew/ks-20191214-skipversions
Ks 20191214 skipversions
This commit is contained in:
commit
69ef68a8cf
|
@ -20,19 +20,16 @@ package ca.uhn.fhir.cli;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.migrate.BaseMigrator;
|
import ca.uhn.fhir.jpa.migrate.*;
|
||||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
import ca.uhn.fhir.jpa.migrate.FlywayMigrator;
|
|
||||||
import ca.uhn.fhir.jpa.migrate.TaskOnlyMigrator;
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
@ -41,12 +38,13 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
* NB since 2019-12-05: This class is kind of weirdly named now, since it can either use Flyway or not use Flyway
|
* NB since 2019-12-05: This class is kind of weirdly named now, since it can either use Flyway or not use Flyway
|
||||||
*/
|
*/
|
||||||
public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends BaseCommand {
|
public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends BaseCommand {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(BaseFlywayMigrateDatabaseCommand.class);
|
||||||
|
|
||||||
public static final String MIGRATE_DATABASE = "migrate-database";
|
public static final String MIGRATE_DATABASE = "migrate-database";
|
||||||
public static final String NO_COLUMN_SHRINK = "no-column-shrink";
|
public static final String NO_COLUMN_SHRINK = "no-column-shrink";
|
||||||
public static final String DONT_USE_FLYWAY = "dont-use-flyway";
|
public static final String DONT_USE_FLYWAY = "dont-use-flyway";
|
||||||
public static final String OUT_OF_ORDER_PERMITTED = "out-of-order-permitted";
|
public static final String OUT_OF_ORDER_PERMITTED = "out-of-order-permitted";
|
||||||
|
public static final String SKIP_VERSIONS = "skip-versions";
|
||||||
private Set<String> myFlags;
|
private Set<String> myFlags;
|
||||||
private String myMigrationTableName;
|
private String myMigrationTableName;
|
||||||
|
|
||||||
|
@ -80,7 +78,6 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
||||||
Options retVal = new Options();
|
Options retVal = new Options();
|
||||||
|
|
||||||
addOptionalOption(retVal, "r", "dry-run", false, "Log the SQL statements that would be executed but to not actually make any changes");
|
addOptionalOption(retVal, "r", "dry-run", false, "Log the SQL statements that would be executed but to not actually make any changes");
|
||||||
|
|
||||||
addRequiredOption(retVal, "u", "url", "URL", "The JDBC database URL");
|
addRequiredOption(retVal, "u", "url", "URL", "The JDBC database URL");
|
||||||
addRequiredOption(retVal, "n", "username", "Username", "The JDBC database username");
|
addRequiredOption(retVal, "n", "username", "Username", "The JDBC database username");
|
||||||
addRequiredOption(retVal, "p", "password", "Password", "The JDBC database password");
|
addRequiredOption(retVal, "p", "password", "Password", "The JDBC database password");
|
||||||
|
@ -89,6 +86,7 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
||||||
addOptionalOption(retVal, null, DONT_USE_FLYWAY,false, "If this option is set, the migrator will not use FlywayDB for migration. This setting should only be used if you are trying to migrate a legacy database platform that is not supported by FlywayDB.");
|
addOptionalOption(retVal, null, DONT_USE_FLYWAY,false, "If this option is set, the migrator will not use FlywayDB for migration. This setting should only be used if you are trying to migrate a legacy database platform that is not supported by FlywayDB.");
|
||||||
addOptionalOption(retVal, null, OUT_OF_ORDER_PERMITTED,false, "If this option is set, the migrator will permit migration tasks to be run out of order. It shouldn't be required in most cases, however may be the solution if you see the error message 'Detected resolved migration not applied to database'.");
|
addOptionalOption(retVal, null, OUT_OF_ORDER_PERMITTED,false, "If this option is set, the migrator will permit migration tasks to be run out of order. It shouldn't be required in most cases, however may be the solution if you see the error message 'Detected resolved migration not applied to database'.");
|
||||||
addOptionalOption(retVal, null, NO_COLUMN_SHRINK, false, "If this flag is set, the system will not attempt to reduce the length of columns. This is useful in environments with a lot of existing data, where shrinking a column can take a very long time.");
|
addOptionalOption(retVal, null, NO_COLUMN_SHRINK, false, "If this flag is set, the system will not attempt to reduce the length of columns. This is useful in environments with a lot of existing data, where shrinking a column can take a very long time.");
|
||||||
|
addOptionalOption(retVal, null, SKIP_VERSIONS, "Versions", "A comma separated list of schema versions to skip. E.g. 4_1_0.20191214.2,4_1_0.20191214.4");
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -137,13 +135,18 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
||||||
migrator.setDryRun(dryRun);
|
migrator.setDryRun(dryRun);
|
||||||
migrator.setNoColumnShrink(noColumnShrink);
|
migrator.setNoColumnShrink(noColumnShrink);
|
||||||
migrator.setOutOfOrderPermitted(outOfOrderPermitted);
|
migrator.setOutOfOrderPermitted(outOfOrderPermitted);
|
||||||
addTasks(migrator);
|
String skipVersions = theCommandLine.getOptionValue(BaseFlywayMigrateDatabaseCommand.SKIP_VERSIONS);
|
||||||
|
addTasks(migrator, skipVersions);
|
||||||
migrator.migrate();
|
migrator.migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void addTasks(BaseMigrator theMigrator);
|
protected abstract void addTasks(BaseMigrator theMigrator, String theSkippedVersions);
|
||||||
|
|
||||||
public void setMigrationTableName(String theMigrationTableName) {
|
public void setMigrationTableName(String theMigrationTableName) {
|
||||||
myMigrationTableName = theMigrationTableName;
|
myMigrationTableName = theMigrationTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setDoNothingOnSkippedTasks(Collection<BaseTask> theTasks, String theSkipVersions) {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(theTasks, theSkipVersions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.cli;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.migrate.BaseMigrator;
|
import ca.uhn.fhir.jpa.migrate.BaseMigrator;
|
||||||
import ca.uhn.fhir.jpa.migrate.FlywayMigrator;
|
|
||||||
import ca.uhn.fhir.jpa.migrate.SchemaMigrator;
|
import ca.uhn.fhir.jpa.migrate.SchemaMigrator;
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
import ca.uhn.fhir.jpa.migrate.tasks.HapiFhirJpaMigrationTasks;
|
import ca.uhn.fhir.jpa.migrate.tasks.HapiFhirJpaMigrationTasks;
|
||||||
|
@ -45,8 +44,9 @@ public class HapiFlywayMigrateDatabaseCommand extends BaseFlywayMigrateDatabaseC
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addTasks(BaseMigrator theMigrator) {
|
protected void addTasks(BaseMigrator theMigrator, String theSkipVersions) {
|
||||||
List<BaseTask<?>> tasks = new HapiFhirJpaMigrationTasks(getFlags()).getAllTasks(VersionEnum.values());
|
List<BaseTask> tasks = new HapiFhirJpaMigrationTasks(getFlags()).getAllTasks(VersionEnum.values());
|
||||||
|
super.setDoNothingOnSkippedTasks(tasks, theSkipVersions);
|
||||||
theMigrator.addTasks(tasks);
|
theMigrator.addTasks(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,15 @@ package ca.uhn.fhir.jpa.migrate;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
import org.flywaydb.core.api.MigrationInfoService;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public abstract class BaseMigrator {
|
public abstract class BaseMigrator implements IMigrator {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(BaseMigrator.class);
|
||||||
|
|
||||||
private boolean myDryRun;
|
private boolean myDryRun;
|
||||||
private boolean myNoColumnShrink;
|
private boolean myNoColumnShrink;
|
||||||
|
@ -39,8 +40,6 @@ public abstract class BaseMigrator {
|
||||||
private String myPassword;
|
private String myPassword;
|
||||||
private List<BaseTask.ExecutedStatement> myExecutedStatements = new ArrayList<>();
|
private List<BaseTask.ExecutedStatement> myExecutedStatements = new ArrayList<>();
|
||||||
|
|
||||||
public abstract void migrate();
|
|
||||||
|
|
||||||
public boolean isDryRun() {
|
public boolean isDryRun() {
|
||||||
return myDryRun;
|
return myDryRun;
|
||||||
}
|
}
|
||||||
|
@ -57,10 +56,6 @@ public abstract class BaseMigrator {
|
||||||
myNoColumnShrink = theNoColumnShrink;
|
myNoColumnShrink = theNoColumnShrink;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Optional<MigrationInfoService> getMigrationInfo();
|
|
||||||
|
|
||||||
public abstract void addTasks(List<BaseTask<?>> theMigrationTasks);
|
|
||||||
|
|
||||||
public DriverTypeEnum getDriverType() {
|
public DriverTypeEnum getDriverType() {
|
||||||
return myDriverType;
|
return myDriverType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class FlywayMigrator extends BaseMigrator {
|
||||||
myMigrationTableName = theMigrationTableName;
|
myMigrationTableName = theMigrationTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTask(BaseTask<?> theTask) {
|
public void addTask(BaseTask theTask) {
|
||||||
myTasks.add(new FlywayMigration(theTask, this));
|
myTasks.add(new FlywayMigration(theTask, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public class FlywayMigrator extends BaseMigrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTasks(List<BaseTask<?>> theTasks) {
|
public void addTasks(List<BaseTask> theTasks) {
|
||||||
theTasks.forEach(this::addTask);
|
theTasks.forEach(this::addTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ca.uhn.fhir.jpa.migrate;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
|
import org.flywaydb.core.api.MigrationInfoService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface IMigrator {
|
||||||
|
|
||||||
|
void migrate();
|
||||||
|
|
||||||
|
Optional<MigrationInfoService> getMigrationInfo();
|
||||||
|
|
||||||
|
void addTasks(List<BaseTask> theMigrationTasks);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ca.uhn.fhir.jpa.migrate;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
public class MigrationTaskSkipper {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(MigrationTaskSkipper.class);
|
||||||
|
|
||||||
|
public static void setDoNothingOnSkippedTasks(Collection<BaseTask> theTasks, String theSkipVersions) {
|
||||||
|
if (isBlank(theSkipVersions) || theTasks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<String> skippedVersionSet = Stream.of(theSkipVersions.split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
// TODO KHS filter out all characters that aren't numbers, periods and underscores
|
||||||
|
.map(s -> s.replace("'", ""))
|
||||||
|
.map(s -> s.replace("\"", ""))
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
for (BaseTask task : theTasks) {
|
||||||
|
if (skippedVersionSet.contains(task.getFlywayVersion())) {
|
||||||
|
ourLog.info("Will skip {}: {}", task.getFlywayVersion(), task.getDescription());
|
||||||
|
task.setDoNothing(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,7 +79,7 @@ public class Migrator {
|
||||||
|
|
||||||
myConnectionProperties = myDriverType.newConnectionProperties(myConnectionUrl, myUsername, myPassword);
|
myConnectionProperties = myDriverType.newConnectionProperties(myConnectionUrl, myUsername, myPassword);
|
||||||
try {
|
try {
|
||||||
for (BaseTask<?> next : myTasks) {
|
for (BaseTask next : myTasks) {
|
||||||
next.setDriverType(myDriverType);
|
next.setDriverType(myDriverType);
|
||||||
next.setConnectionProperties(myConnectionProperties);
|
next.setConnectionProperties(myConnectionProperties);
|
||||||
next.setDryRun(myDryRun);
|
next.setDryRun(myDryRun);
|
||||||
|
@ -125,7 +125,7 @@ public class Migrator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTasks(List<BaseTask<?>> theTasks) {
|
public void addTasks(List<BaseTask> theTasks) {
|
||||||
theTasks.forEach(this::addTask);
|
theTasks.forEach(this::addTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,12 @@ import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class SchemaMigrator {
|
public class SchemaMigrator {
|
||||||
public static final String HAPI_FHIR_MIGRATION_TABLENAME = "FLY_HFJ_MIGRATION";
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(SchemaMigrator.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(SchemaMigrator.class);
|
||||||
|
public static final String HAPI_FHIR_MIGRATION_TABLENAME = "FLY_HFJ_MIGRATION";
|
||||||
private final BasicDataSource myDataSource;
|
private final BasicDataSource myDataSource;
|
||||||
private final boolean mySkipValidation;
|
private final boolean mySkipValidation;
|
||||||
private final String myMigrationTableName;
|
private final String myMigrationTableName;
|
||||||
private final List<BaseTask<?>> myMigrationTasks;
|
private final List<BaseTask> myMigrationTasks;
|
||||||
private boolean myDontUseFlyway;
|
private boolean myDontUseFlyway;
|
||||||
private boolean myOutOfOrderPermitted;
|
private boolean myOutOfOrderPermitted;
|
||||||
private DriverTypeEnum myDriverType;
|
private DriverTypeEnum myDriverType;
|
||||||
|
@ -49,7 +49,7 @@ public class SchemaMigrator {
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public SchemaMigrator(String theMigrationTableName, BasicDataSource theDataSource, Properties jpaProperties, List<BaseTask<?>> theMigrationTasks) {
|
public SchemaMigrator(String theMigrationTableName, BasicDataSource theDataSource, Properties jpaProperties, List<BaseTask> theMigrationTasks) {
|
||||||
myDataSource = theDataSource;
|
myDataSource = theDataSource;
|
||||||
myMigrationTableName = theMigrationTableName;
|
myMigrationTableName = theMigrationTableName;
|
||||||
myMigrationTasks = theMigrationTasks;
|
myMigrationTasks = theMigrationTasks;
|
||||||
|
|
|
@ -38,13 +38,13 @@ import java.util.Optional;
|
||||||
public class TaskOnlyMigrator extends BaseMigrator {
|
public class TaskOnlyMigrator extends BaseMigrator {
|
||||||
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(TaskOnlyMigrator.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(TaskOnlyMigrator.class);
|
||||||
private List<BaseTask<?>> myTasks = new ArrayList<>();
|
private List<BaseTask> myTasks = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void migrate() {
|
public void migrate() {
|
||||||
DriverTypeEnum.ConnectionProperties connectionProperties = getDriverType().newConnectionProperties(getConnectionUrl(), getUsername(), getPassword());
|
DriverTypeEnum.ConnectionProperties connectionProperties = getDriverType().newConnectionProperties(getConnectionUrl(), getUsername(), getPassword());
|
||||||
|
|
||||||
for (BaseTask<?> next : myTasks) {
|
for (BaseTask next : myTasks) {
|
||||||
next.setDriverType(getDriverType());
|
next.setDriverType(getDriverType());
|
||||||
next.setDryRun(isDryRun());
|
next.setDryRun(isDryRun());
|
||||||
next.setNoColumnShrink(isNoColumnShrink());
|
next.setNoColumnShrink(isNoColumnShrink());
|
||||||
|
@ -71,7 +71,7 @@ public class TaskOnlyMigrator extends BaseMigrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTasks(List<BaseTask<?>> theMigrationTasks) {
|
public void addTasks(List<BaseTask> theMigrationTasks) {
|
||||||
myTasks.addAll(theMigrationTasks);
|
myTasks.addAll(theMigrationTasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,16 +33,16 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BaseMigrationTasks<T extends Enum> {
|
public class BaseMigrationTasks<T extends Enum> {
|
||||||
private Multimap<T, BaseTask<?>> myTasks = MultimapBuilder.hashKeys().arrayListValues().build();
|
private Multimap<T, BaseTask> myTasks = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||||
MigrationVersion lastVersion;
|
MigrationVersion lastVersion;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<BaseTask<?>> getTasks(@Nonnull T theFrom, @Nonnull T theTo) {
|
public List<BaseTask> getTasks(@Nonnull T theFrom, @Nonnull T theTo) {
|
||||||
Validate.notNull(theFrom);
|
Validate.notNull(theFrom);
|
||||||
Validate.notNull(theTo);
|
Validate.notNull(theTo);
|
||||||
Validate.isTrue(theFrom.ordinal() < theTo.ordinal(), "From version must be lower than to version");
|
Validate.isTrue(theFrom.ordinal() < theTo.ordinal(), "From version must be lower than to version");
|
||||||
|
|
||||||
List<BaseTask<?>> retVal = new ArrayList<>();
|
List<BaseTask> retVal = new ArrayList<>();
|
||||||
for (Object nextVersion : EnumUtils.getEnumList(theFrom.getClass())) {
|
for (Object nextVersion : EnumUtils.getEnumList(theFrom.getClass())) {
|
||||||
if (((T) nextVersion).ordinal() <= theFrom.ordinal()) {
|
if (((T) nextVersion).ordinal() <= theFrom.ordinal()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -51,7 +51,7 @@ public class BaseMigrationTasks<T extends Enum> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<BaseTask<?>> nextValues = myTasks.get((T) nextVersion);
|
Collection<BaseTask> nextValues = myTasks.get((T) nextVersion);
|
||||||
if (nextValues != null) {
|
if (nextValues != null) {
|
||||||
retVal.addAll(nextValues);
|
retVal.addAll(nextValues);
|
||||||
}
|
}
|
||||||
|
@ -68,10 +68,10 @@ public class BaseMigrationTasks<T extends Enum> {
|
||||||
return new Builder(theRelease.name(), sink);
|
return new Builder(theRelease.name(), sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseTask<?>> getAllTasks(T[] theVersionEnumValues) {
|
public List<BaseTask> getAllTasks(T[] theVersionEnumValues) {
|
||||||
List<BaseTask<?>> retval = new ArrayList<>();
|
List<BaseTask> retval = new ArrayList<>();
|
||||||
for (T nextVersion : theVersionEnumValues) {
|
for (T nextVersion : theVersionEnumValues) {
|
||||||
Collection<BaseTask<?>> nextValues = myTasks.get(nextVersion);
|
Collection<BaseTask> nextValues = myTasks.get(nextVersion);
|
||||||
if (nextValues != null) {
|
if (nextValues != null) {
|
||||||
validate(nextValues);
|
validate(nextValues);
|
||||||
retval.addAll(nextValues);
|
retval.addAll(nextValues);
|
||||||
|
@ -81,7 +81,7 @@ public class BaseMigrationTasks<T extends Enum> {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(Collection<BaseTask<?>> theTasks) {
|
void validate(Collection<BaseTask> theTasks) {
|
||||||
for (BaseTask task: theTasks) {
|
for (BaseTask task: theTasks) {
|
||||||
task.validateVersion();
|
task.validateVersion();
|
||||||
String version = task.getFlywayVersion();
|
String version = task.getFlywayVersion();
|
||||||
|
@ -96,6 +96,6 @@ public class BaseMigrationTasks<T extends Enum> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IAcceptsTasks {
|
public interface IAcceptsTasks {
|
||||||
void addTask(BaseTask<?> theTask);
|
void addTask(BaseTask theTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class Builder {
|
||||||
return new BuilderWithTableName(myRelease, mySink, theTableName);
|
return new BuilderWithTableName(myRelease, mySink, theTableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTask(BaseTask<?> theTask) {
|
public void addTask(BaseTask theTask) {
|
||||||
mySink.addTask(theTask);
|
mySink.addTask(theTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTask(BaseTask<?> theTask) {
|
public void addTask(BaseTask theTask) {
|
||||||
if (theTask instanceof AddColumnTask) {
|
if (theTask instanceof AddColumnTask) {
|
||||||
myTask.addAddColumnTask((AddColumnTask) theTask);
|
myTask.addAddColumnTask((AddColumnTask) theTask);
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,7 +202,7 @@ public class Builder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTask(BaseTask<?> theTask) {
|
public void addTask(BaseTask theTask) {
|
||||||
((BaseTableTask<?>) theTask).setTableName(myTableName);
|
((BaseTableTask<?>) theTask).setTableName(myTableName);
|
||||||
mySink.addTask(theTask);
|
mySink.addTask(theTask);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package ca.uhn.fhir.jpa.migrate;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
|
import ca.uhn.fhir.jpa.migrate.taskdef.DropIndexTask;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
public class MigrationTaskSkipperTest {
|
||||||
|
public static final String RELEASE = "4_1_0";
|
||||||
|
public static final String DATE_PREFIX = "20191214.";
|
||||||
|
private static final String VERSION_PREFIX = RELEASE + "." + DATE_PREFIX;
|
||||||
|
private List<BaseTask> myTasks;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
myTasks = new ArrayList<>();
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 1));
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 2));
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 3));
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 4));
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 5));
|
||||||
|
myTasks.add(new DropIndexTask(RELEASE, DATE_PREFIX + 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skipNull() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, null);
|
||||||
|
assertSkipped(myTasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skipAll() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, makeSkipString(1, 2, 3, 4, 5, 6));
|
||||||
|
assertSkipped(myTasks, 1, 2, 3, 4, 5, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skipOne() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, makeSkipString(4));
|
||||||
|
assertSkipped(myTasks, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skipTwo() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, VERSION_PREFIX + 2 + "," + VERSION_PREFIX + 3);
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void skipWeirdSpacing() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, " " + VERSION_PREFIX + 2 + " , " + VERSION_PREFIX + 3 + " ");
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleComma() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, VERSION_PREFIX + 2 + ",," + VERSION_PREFIX + 3);
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void startComma() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, "," + VERSION_PREFIX + 2 + "," + VERSION_PREFIX + 3);
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void quoted() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, "\"" + VERSION_PREFIX + 2 + "," + VERSION_PREFIX + 3 + "\"");
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allQuoted() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, "\"" + VERSION_PREFIX + 2 + "\",\"" + VERSION_PREFIX + 3 + "\"");
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneQuoted() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, "\"" + VERSION_PREFIX + 2 + "\"" );
|
||||||
|
assertSkipped(myTasks, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void endComma() {
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(myTasks, VERSION_PREFIX + 2 + "," + VERSION_PREFIX + 3 + ",");
|
||||||
|
assertSkipped(myTasks, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeSkipString(Integer... theVersions) {
|
||||||
|
return integersToVersions(theVersions).collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSkipped(List<BaseTask> theTasks, Integer... theVersions) {
|
||||||
|
Set<String> expectedVersions = integersToVersions(theVersions).collect(Collectors.toSet());
|
||||||
|
Set<String> taskVersions = theTasks.stream().filter(BaseTask::isDoNothing).map(BaseTask::getFlywayVersion).collect(Collectors.toSet());
|
||||||
|
assertThat(taskVersions, equalTo(expectedVersions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Stream<String> integersToVersions(Integer[] theVersions) {
|
||||||
|
return Stream.of(theVersions).map(s -> VERSION_PREFIX + s);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.migrate;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.AddTableRawSqlTask;
|
import ca.uhn.fhir.jpa.migrate.taskdef.AddTableRawSqlTask;
|
||||||
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTest;
|
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTest;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import org.flywaydb.core.api.FlywayException;
|
import org.flywaydb.core.api.FlywayException;
|
||||||
|
@ -66,6 +67,35 @@ public class SchemaMigratorTest extends BaseTest {
|
||||||
schemaMigrator.migrate();
|
schemaMigrator.migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSkipSchemaVersion() throws SQLException {
|
||||||
|
AddTableRawSqlTask taskA = new AddTableRawSqlTask("V4_1_0", "20191214.1");
|
||||||
|
taskA.setTableName("SOMETABLE_A");
|
||||||
|
taskA.addSql(DriverTypeEnum.H2_EMBEDDED, "create table SOMETABLE_A (PID bigint not null, TEXTCOL varchar(255))");
|
||||||
|
|
||||||
|
AddTableRawSqlTask taskB = new AddTableRawSqlTask("V4_1_0", "20191214.2");
|
||||||
|
taskB.setTableName("SOMETABLE_B");
|
||||||
|
taskB.addSql(DriverTypeEnum.H2_EMBEDDED, "create table SOMETABLE_B (PID bigint not null, TEXTCOL varchar(255))");
|
||||||
|
|
||||||
|
AddTableRawSqlTask taskC = new AddTableRawSqlTask("V4_1_0", "20191214.3");
|
||||||
|
taskC.setTableName("SOMETABLE_C");
|
||||||
|
taskC.addSql(DriverTypeEnum.H2_EMBEDDED, "create table SOMETABLE_C (PID bigint not null, TEXTCOL varchar(255))");
|
||||||
|
|
||||||
|
AddTableRawSqlTask taskD = new AddTableRawSqlTask("V4_1_0", "20191214.4");
|
||||||
|
taskD.setTableName("SOMETABLE_D");
|
||||||
|
taskD.addSql(DriverTypeEnum.H2_EMBEDDED, "create table SOMETABLE_D (PID bigint not null, TEXTCOL varchar(255))");
|
||||||
|
|
||||||
|
ImmutableList<BaseTask> taskList = ImmutableList.of(taskA, taskB, taskC, taskD);
|
||||||
|
MigrationTaskSkipper.setDoNothingOnSkippedTasks(taskList, "4_1_0.20191214.2, 4_1_0.20191214.4");
|
||||||
|
SchemaMigrator schemaMigrator = new SchemaMigrator(SchemaMigrator.HAPI_FHIR_MIGRATION_TABLENAME, getDataSource(), new Properties(), taskList);
|
||||||
|
schemaMigrator.setDriverType(DriverTypeEnum.H2_EMBEDDED);
|
||||||
|
|
||||||
|
schemaMigrator.migrate();
|
||||||
|
|
||||||
|
DriverTypeEnum.ConnectionProperties connectionProperties = DriverTypeEnum.H2_EMBEDDED.newConnectionProperties(getDataSource().getUrl(), getDataSource().getUsername(), getDataSource().getPassword());
|
||||||
|
Set<String> tableNames = JdbcUtils.getTableNames(connectionProperties);
|
||||||
|
assertThat(tableNames, Matchers.containsInAnyOrder("SOMETABLE_A", "SOMETABLE_C"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMigrationRequiredNoFlyway() throws SQLException {
|
public void testMigrationRequiredNoFlyway() throws SQLException {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class HashTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCheckAllHashes() {
|
public void testCheckAllHashes() {
|
||||||
List<BaseTask<?>> tasks1 = new HapiFhirJpaMigrationTasks(Collections.emptySet()).getAllTasks(VersionEnum.values());
|
List<BaseTask> tasks1 = new HapiFhirJpaMigrationTasks(Collections.emptySet()).getAllTasks(VersionEnum.values());
|
||||||
Map<String, Integer> hashesByVersion = new HashMap<>();
|
Map<String, Integer> hashesByVersion = new HashMap<>();
|
||||||
for (BaseTask task : tasks1) {
|
for (BaseTask task : tasks1) {
|
||||||
String version = task.getFlywayVersion();
|
String version = task.getFlywayVersion();
|
||||||
|
@ -41,7 +41,7 @@ public class HashTest {
|
||||||
hashesByVersion.put(version, task.hashCode());
|
hashesByVersion.put(version, task.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BaseTask<?>> tasks2 = new HapiFhirJpaMigrationTasks(Collections.emptySet()).getAllTasks(VersionEnum.values());
|
List<BaseTask> tasks2 = new HapiFhirJpaMigrationTasks(Collections.emptySet()).getAllTasks(VersionEnum.values());
|
||||||
for (BaseTask task : tasks2) {
|
for (BaseTask task : tasks2) {
|
||||||
String version = task.getFlywayVersion();
|
String version = task.getFlywayVersion();
|
||||||
int origHash = hashesByVersion.get(version);
|
int origHash = hashesByVersion.get(version);
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class BaseMigrationTasksTest {
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCorrectOrder() {
|
public void testValidateCorrectOrder() {
|
||||||
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
||||||
List<BaseTask<?>> tasks = new ArrayList<>();
|
List<BaseTask> tasks = new ArrayList<>();
|
||||||
tasks.add(new DropTableTask("1", "20191029.1"));
|
tasks.add(new DropTableTask("1", "20191029.1"));
|
||||||
tasks.add(new DropTableTask("1", "20191029.2"));
|
tasks.add(new DropTableTask("1", "20191029.2"));
|
||||||
migrationTasks.validate(tasks);
|
migrationTasks.validate(tasks);
|
||||||
|
@ -26,7 +26,7 @@ public class BaseMigrationTasksTest {
|
||||||
@Test
|
@Test
|
||||||
public void testValidateVersionWrongOrder() {
|
public void testValidateVersionWrongOrder() {
|
||||||
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
||||||
List<BaseTask<?>> tasks = new ArrayList<>();
|
List<BaseTask> tasks = new ArrayList<>();
|
||||||
tasks.add(new DropTableTask("1", "20191029.2"));
|
tasks.add(new DropTableTask("1", "20191029.2"));
|
||||||
tasks.add(new DropTableTask("1", "20191029.1"));
|
tasks.add(new DropTableTask("1", "20191029.1"));
|
||||||
try {
|
try {
|
||||||
|
@ -40,7 +40,7 @@ public class BaseMigrationTasksTest {
|
||||||
@Test
|
@Test
|
||||||
public void testValidateSameVersion() {
|
public void testValidateSameVersion() {
|
||||||
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
||||||
List<BaseTask<?>> tasks = new ArrayList<>();
|
List<BaseTask> tasks = new ArrayList<>();
|
||||||
tasks.add(new DropTableTask("1", "20191029.1"));
|
tasks.add(new DropTableTask("1", "20191029.1"));
|
||||||
tasks.add(new DropTableTask("1", "20191029.1"));
|
tasks.add(new DropTableTask("1", "20191029.1"));
|
||||||
try {
|
try {
|
||||||
|
@ -54,7 +54,7 @@ public class BaseMigrationTasksTest {
|
||||||
@Test
|
@Test
|
||||||
public void testValidateWrongDateOrder() {
|
public void testValidateWrongDateOrder() {
|
||||||
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
MyMigrationTasks migrationTasks = new MyMigrationTasks();
|
||||||
List<BaseTask<?>> tasks = new ArrayList<>();
|
List<BaseTask> tasks = new ArrayList<>();
|
||||||
tasks.add(new DropTableTask("1", "20191029.1"));
|
tasks.add(new DropTableTask("1", "20191029.1"));
|
||||||
tasks.add(new DropTableTask("1", "20191028.1"));
|
tasks.add(new DropTableTask("1", "20191028.1"));
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue