use of org.flywaydb.core.internal.info.MigrationInfoServiceImpl in project killbill by killbill.
the class DbMigrateWithDryRun method dryRunMigrate.
public int dryRunMigrate() throws FlywayException {
try {
for (final FlywayCallback callback : callbacks) {
new TransactionTemplate(connectionUserObjects).execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction() throws SQLException {
dbSupportUserObjects.changeCurrentSchemaTo(schema);
callback.beforeMigrate(connectionUserObjects);
return null;
}
});
}
// PIERRE: perform a single query to the metadata table
final MigrationInfoServiceImpl infoService = new MigrationInfoServiceImpl(migrationResolver, metaDataTableForDryRun, target, outOfOrder, true, true);
infoService.refresh();
final MigrationInfoImpl[] pendingMigrations = infoService.pending();
new TransactionTemplate(connectionMetaDataTable, false).execute(new TransactionCallback<Boolean>() {
public Boolean doInTransaction() {
int i = 1;
for (final MigrationInfoImpl migrationInfo : pendingMigrations) {
applyMigration(i, migrationInfo);
i++;
}
return true;
}
});
for (final FlywayCallback callback : callbacks) {
new TransactionTemplate(connectionUserObjects).execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction() throws SQLException {
dbSupportUserObjects.changeCurrentSchemaTo(schema);
callback.afterMigrate(connectionUserObjects);
return null;
}
});
}
return pendingMigrations.length;
} finally {
dbSupportUserObjects.restoreCurrentSchema();
}
}
use of org.flywaydb.core.internal.info.MigrationInfoServiceImpl in project flyway by flyway.
the class DbInfo method info.
public MigrationInfoService info() {
callbackExecutor.onEvent(Event.BEFORE_INFO);
MigrationInfoServiceImpl migrationInfoService;
try {
migrationInfoService = new MigrationInfoServiceImpl(migrationResolver, schemaHistory, database, configuration, configuration.getTarget(), configuration.isOutOfOrder(), configuration.getCherryPick(), true, true, true, true);
migrationInfoService.refresh();
migrationInfoService.setAllSchemasEmpty(schemas);
} catch (FlywayException e) {
callbackExecutor.onEvent(Event.AFTER_INFO_ERROR);
throw e;
}
callbackExecutor.onEvent(Event.AFTER_INFO);
return migrationInfoService;
}
use of org.flywaydb.core.internal.info.MigrationInfoServiceImpl in project flyway by flyway.
the class Flyway method info.
/**
* <p>Retrieves the complete information about all the migrations including applied, pending and current migrations with
* details and status.</p>
* <img src="https://flywaydb.org/assets/balsamiq/command-info.png" alt="info">
*
* @return All migrations sorted by version, oldest first.
* @throws FlywayException when the info retrieval failed.
*/
public MigrationInfoService info() {
return execute(new Command<MigrationInfoService>() {
public MigrationInfoService execute(final Connection connectionMetaDataTable, MigrationResolver migrationResolver, MetaDataTable metaDataTable, final DbSupport dbSupport, final Schema[] schemas, FlywayCallback[] flywayCallbacks) {
try {
for (final FlywayCallback callback : flywayCallbacks) {
new TransactionTemplate(connectionMetaDataTable).execute(new Callable<Object>() {
@Override
public Object call() throws SQLException {
dbSupport.changeCurrentSchemaTo(schemas[0]);
callback.beforeInfo(connectionMetaDataTable);
return null;
}
});
}
MigrationInfoServiceImpl migrationInfoService = new MigrationInfoServiceImpl(migrationResolver, metaDataTable, target, outOfOrder, true, true, true);
migrationInfoService.refresh();
for (final FlywayCallback callback : flywayCallbacks) {
new TransactionTemplate(connectionMetaDataTable).execute(new Callable<Object>() {
@Override
public Object call() throws SQLException {
dbSupport.changeCurrentSchemaTo(schemas[0]);
callback.afterInfo(connectionMetaDataTable);
return null;
}
});
}
return migrationInfoService;
} finally {
dbSupport.restoreCurrentSchema();
}
}
});
}
use of org.flywaydb.core.internal.info.MigrationInfoServiceImpl in project flyway by flyway.
the class DbMigrate method migrateGroup.
/**
* Migrate a group of one (group = false) or more (group = true) migrations.
*
* @param firstRun Whether this is the first time this code runs in this migration run.
* @return The number of newly applied migrations.
*/
private Integer migrateGroup(boolean firstRun) {
MigrationInfoServiceImpl infoService = new MigrationInfoServiceImpl(migrationResolver, schemaHistory, database, configuration, configuration.getTarget(), configuration.isOutOfOrder(), configuration.getCherryPick(), true, true, true, true);
infoService.refresh();
MigrationInfo current = infoService.current();
MigrationVersion currentSchemaVersion = current == null ? MigrationVersion.EMPTY : current.getVersion();
if (firstRun) {
LOG.info("Current version of schema " + schema + ": " + currentSchemaVersion);
MigrationVersion schemaVersionToOutput = currentSchemaVersion == null ? MigrationVersion.EMPTY : currentSchemaVersion;
migrateResult.initialSchemaVersion = schemaVersionToOutput.getVersion();
if (configuration.isOutOfOrder()) {
String outOfOrderWarning = "outOfOrder mode is active. Migration of schema " + schema + " may not be reproducible.";
LOG.warn(outOfOrderWarning);
migrateResult.warnings.add(outOfOrderWarning);
}
}
MigrationInfo[] future = infoService.future();
if (future.length > 0) {
List<MigrationInfo> resolved = Arrays.asList(infoService.resolved());
Collections.reverse(resolved);
if (resolved.isEmpty()) {
LOG.error("Schema " + schema + " has version " + currentSchemaVersion + ", but no migration could be resolved in the configured locations !");
} else {
for (MigrationInfo migrationInfo : resolved) {
// Only consider versioned migrations
if (migrationInfo.getVersion() != null) {
LOG.warn("Schema " + schema + " has a version (" + currentSchemaVersion + ") that is newer than the latest available migration (" + migrationInfo.getVersion() + ") !");
break;
}
}
}
}
MigrationInfoImpl[] failed = infoService.failed();
if (failed.length > 0) {
if ((failed.length == 1) && (failed[0].getState() == MigrationState.FUTURE_FAILED) && configuration.isIgnoreFutureMigrations()) {
LOG.warn("Schema " + schema + " contains a failed future migration to version " + failed[0].getVersion() + " !");
} else {
final boolean inTransaction = failed[0].canExecuteInTransaction();
if (failed[0].getVersion() == null) {
throw new FlywayMigrateException(failed[0], "Schema " + schema + " contains a failed repeatable migration (" + doQuote(failed[0].getDescription()) + ") !", inTransaction, migrateResult);
}
throw new FlywayMigrateException(failed[0], "Schema " + schema + " contains a failed migration to version " + failed[0].getVersion() + " !", inTransaction, migrateResult);
}
}
LinkedHashMap<MigrationInfoImpl, Boolean> group = new LinkedHashMap<>();
for (MigrationInfoImpl pendingMigration : infoService.pending()) {
if (appliedResolvedMigrations.contains(pendingMigration.getResolvedMigration())) {
continue;
}
boolean isOutOfOrder = pendingMigration.getVersion() != null && pendingMigration.getVersion().compareTo(currentSchemaVersion) < 0;
group.put(pendingMigration, isOutOfOrder);
if (!configuration.isGroup()) {
// Only include one pending migration if group is disabled
break;
}
}
if (!group.isEmpty()) {
boolean skipExecutingMigrations = false;
applyMigrations(group, skipExecutingMigrations);
}
return group.size();
}
use of org.flywaydb.core.internal.info.MigrationInfoServiceImpl in project flyway by flyway.
the class DbValidate method validate.
/**
* Starts the actual migration.
*
* @return The validation error, if any.
*/
public ValidateResult validate() {
if (!schema.exists()) {
if (!migrationResolver.resolveMigrations(new Context() {
@Override
public Configuration getConfiguration() {
return configuration;
}
}).isEmpty() && !pending) {
String validationErrorMessage = "Schema " + schema + " doesn't exist yet";
ErrorDetails validationError = new ErrorDetails(ErrorCode.SCHEMA_DOES_NOT_EXIST, validationErrorMessage);
return CommandResultFactory.createValidateResult(database.getCatalog(), validationError, 0, null, new ArrayList<>());
}
return CommandResultFactory.createValidateResult(database.getCatalog(), null, 0, null, new ArrayList<>());
}
callbackExecutor.onEvent(Event.BEFORE_VALIDATE);
LOG.debug("Validating migrations ...");
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Pair<Integer, List<ValidateOutput>> result = ExecutionTemplateFactory.createExecutionTemplate(connection.getJdbcConnection(), database).execute(new Callable<Pair<Integer, List<ValidateOutput>>>() {
@Override
public Pair<Integer, List<ValidateOutput>> call() {
MigrationInfoServiceImpl migrationInfoService = new MigrationInfoServiceImpl(migrationResolver, schemaHistory, database, configuration, configuration.getTarget(), configuration.isOutOfOrder(), configuration.getCherryPick(), pending, configuration.isIgnoreMissingMigrations(), configuration.isIgnoreIgnoredMigrations(), configuration.isIgnoreFutureMigrations());
migrationInfoService.refresh();
int count = migrationInfoService.all().length;
List<ValidateOutput> invalidMigrations = migrationInfoService.validate();
return Pair.of(count, invalidMigrations);
}
});
stopWatch.stop();
List<String> warnings = new ArrayList<>();
List<ValidateOutput> invalidMigrations = result.getRight();
ErrorDetails validationError = null;
int count = 0;
if (invalidMigrations.isEmpty()) {
count = result.getLeft();
if (count == 1) {
LOG.info(String.format("Successfully validated 1 migration (execution time %s)", TimeFormat.format(stopWatch.getTotalTimeMillis())));
} else {
LOG.info(String.format("Successfully validated %d migrations (execution time %s)", count, TimeFormat.format(stopWatch.getTotalTimeMillis())));
if (count == 0) {
String noMigrationsWarning = "No migrations found. Are your locations set up correctly?";
warnings.add(noMigrationsWarning);
LOG.warn(noMigrationsWarning);
}
}
callbackExecutor.onEvent(Event.AFTER_VALIDATE);
} else {
validationError = new ErrorDetails(ErrorCode.VALIDATE_ERROR, "Migrations have failed validation");
callbackExecutor.onEvent(Event.AFTER_VALIDATE_ERROR);
}
return CommandResultFactory.createValidateResult(database.getCatalog(), validationError, count, invalidMigrations, warnings);
}
Aggregations