use of org.flywaydb.core.internal.schemahistory.AppliedMigration in project flyway by flyway.
the class MigrationInfoServiceImpl method refresh.
/**
* Refreshes the info about all known migrations from both the classpath and the DB.
*/
public void refresh() {
Collection<ResolvedMigration> resolvedMigrations = migrationResolver.resolveMigrations(context);
List<AppliedMigration> appliedMigrations = schemaHistory.allAppliedMigrations();
MigrationInfoContext context = new MigrationInfoContext();
context.outOfOrder = outOfOrder;
context.pending = pending;
context.missing = missing;
context.ignored = ignored;
context.future = future;
context.ignorePatterns = configuration.getIgnoreMigrationPatterns();
context.target = target;
context.cherryPick = cherryPick;
Map<Pair<MigrationVersion, Boolean>, ResolvedMigration> resolvedVersioned = new TreeMap<>();
Map<String, ResolvedMigration> resolvedRepeatable = new TreeMap<>();
ResolvedMigration pendingBaselineMigration = null;
AppliedMigration appliedBaselineMigration = null;
// Separate resolved migrations into versioned and repeatable
for (ResolvedMigration resolvedMigration : resolvedMigrations) {
MigrationVersion version = resolvedMigration.getVersion();
if (version != null) {
if (version.compareTo(context.lastResolved) > 0) {
context.lastResolved = version;
}
if (resolvedMigration.getType().isBaselineMigration() && version.compareTo(context.latestBaselineMigration) > 0) {
} else {
// noinspection RedundantConditionalExpression
resolvedVersioned.put(Pair.of(version, false), resolvedMigration);
}
} else {
resolvedRepeatable.put(resolvedMigration.getDescription(), resolvedMigration);
}
}
// Split applied into version and repeatable, and update state from synthetic migrations
List<Pair<AppliedMigration, AppliedMigrationAttributes>> appliedVersioned = new ArrayList<>();
List<Pair<AppliedMigration, AppliedMigrationAttributes>> appliedRepeatable = new ArrayList<>();
for (AppliedMigration appliedMigration : appliedMigrations) {
MigrationVersion version = appliedMigration.getVersion();
if (version == null) {
appliedRepeatable.add(Pair.of(appliedMigration, new AppliedMigrationAttributes()));
if (appliedMigration.getType().equals(MigrationType.DELETE) && appliedMigration.isSuccess()) {
markRepeatableAsDeleted(appliedMigration.getDescription(), appliedRepeatable);
}
continue;
}
if (appliedMigration.getType() == MigrationType.SCHEMA) {
context.schema = version;
}
if (appliedMigration.getType() == MigrationType.BASELINE) {
context.baseline = version;
}
if (appliedMigration.getType().equals(MigrationType.DELETE) && appliedMigration.isSuccess()) {
markAsDeleted(version, appliedVersioned);
}
appliedVersioned.add(Pair.of(appliedMigration, new AppliedMigrationAttributes()));
}
// Update last applied and out of order states
for (Pair<AppliedMigration, AppliedMigrationAttributes> av : appliedVersioned) {
AppliedMigration appliedMigration = av.getLeft();
MigrationVersion version = appliedMigration.getVersion();
if (version != null) {
if (version.compareTo(context.lastApplied) > 0) {
if (av.getLeft().getType() != MigrationType.DELETE && !av.getRight().deleted) {
context.lastApplied = version;
}
} else {
av.getRight().outOfOrder = true;
}
}
}
// Set target
if (MigrationVersion.CURRENT == target) {
context.target = context.lastApplied;
}
// Identify pending versioned migrations and build output migration info list
List<MigrationInfoImpl> migrationInfos1 = new ArrayList<>();
Set<ResolvedMigration> pendingResolvedVersioned = new HashSet<>(resolvedVersioned.values());
for (Pair<AppliedMigration, AppliedMigrationAttributes> av : appliedVersioned) {
ResolvedMigration resolvedMigration = resolvedVersioned.get(Pair.of(av.getLeft().getVersion(), av.getLeft().getType().isUndo()));
// Remove pending migrations
if (resolvedMigration != null && !av.getRight().deleted && av.getLeft().getType() != MigrationType.DELETE) {
pendingResolvedVersioned.remove(resolvedMigration);
}
// Build final migration info
migrationInfos1.add(new MigrationInfoImpl(resolvedMigration, av.getLeft(), context, av.getRight().outOfOrder, av.getRight().deleted, av.getRight().undone));
}
// Add all pending migrations to output list
for (ResolvedMigration prv : pendingResolvedVersioned) {
if (prv.getVersion().compareTo(context.latestBaselineMigration) <= 0) {
continue;
}
migrationInfos1.add(new MigrationInfoImpl(prv, null, context, false, false, false));
}
if (pendingBaselineMigration != null) {
migrationInfos1.add(new MigrationInfoImpl(pendingBaselineMigration, null, context, false, false, false));
}
if (configuration.isFailOnMissingTarget() && target != null && target != MigrationVersion.CURRENT && target != MigrationVersion.LATEST && target != MigrationVersion.NEXT) {
boolean targetFound = false;
for (MigrationInfoImpl migration : migrationInfos1) {
if (target.compareTo(migration.getVersion()) == 0) {
targetFound = true;
break;
}
}
if (!targetFound) {
throw new FlywayException("No migration with a target version " + target + " could be found. Ensure target is specified correctly and the migration exists.");
}
}
// Setup the latest repeatable run ranks
for (Pair<AppliedMigration, AppliedMigrationAttributes> av : appliedRepeatable) {
if (av.getRight().deleted && av.getLeft().getType() == MigrationType.DELETE) {
continue;
}
AppliedMigration appliedRepeatableMigration = av.getLeft();
String desc = appliedRepeatableMigration.getDescription();
int rank = appliedRepeatableMigration.getInstalledRank();
Map<String, Integer> latestRepeatableRuns = context.latestRepeatableRuns;
if (!latestRepeatableRuns.containsKey(desc) || (rank > latestRepeatableRuns.get(desc))) {
latestRepeatableRuns.put(desc, rank);
}
}
// Using latest repeatable runs, discover pending repeatables and build output list
Set<ResolvedMigration> pendingResolvedRepeatable = new HashSet<>(resolvedRepeatable.values());
for (Pair<AppliedMigration, AppliedMigrationAttributes> av : appliedRepeatable) {
AppliedMigration appliedRepeatableMigration = av.getLeft();
String desc = appliedRepeatableMigration.getDescription();
int rank = appliedRepeatableMigration.getInstalledRank();
ResolvedMigration resolvedMigration = resolvedRepeatable.get(desc);
int latestRank = context.latestRepeatableRuns.get(desc);
// If latest run is the same rank, its not pending
if (!av.getRight().deleted && av.getLeft().getType() != MigrationType.DELETE && resolvedMigration != null && rank == latestRank && resolvedMigration.checksumMatches(appliedRepeatableMigration.getChecksum())) {
pendingResolvedRepeatable.remove(resolvedMigration);
}
// Add to output list
migrationInfos1.add(new MigrationInfoImpl(resolvedMigration, appliedRepeatableMigration, context, false, av.getRight().deleted, false));
}
// Add pending repeatables to output list
for (ResolvedMigration prr : pendingResolvedRepeatable) {
migrationInfos1.add(new MigrationInfoImpl(prr, null, context, false, false, false));
}
// Set output
Collections.sort(migrationInfos1);
migrationInfos = migrationInfos1;
if (context.target == MigrationVersion.NEXT) {
MigrationInfo[] pendingMigrationInfos = pending();
if (pendingMigrationInfos.length == 0) {
context.target = null;
} else {
context.target = pendingMigrationInfos[0].getVersion();
}
}
}
use of org.flywaydb.core.internal.schemahistory.AppliedMigration in project flyway by flyway.
the class DbBaseline method baseline.
/**
* Baselines the database.
*/
public BaselineResult baseline() {
callbackExecutor.onEvent(Event.BEFORE_BASELINE);
try {
if (!schemaHistory.exists()) {
schemaHistory.create(true);
LOG.info("Successfully baselined schema with version: " + baselineVersion);
baselineResult.successfullyBaselined = true;
baselineResult.baselineVersion = baselineVersion.toString();
} else {
AppliedMigration baselineMarker = schemaHistory.getBaselineMarker();
if (baselineMarker != null) {
if (baselineVersion.equals(baselineMarker.getVersion()) && baselineDescription.equals(baselineMarker.getDescription())) {
LOG.info("Schema history table " + schemaHistory + " already initialized with (" + baselineVersion + "," + baselineDescription + "). Skipping.");
baselineResult.successfullyBaselined = true;
baselineResult.baselineVersion = baselineVersion.toString();
} else {
throw new FlywayException("Unable to baseline schema history table " + schemaHistory + " with (" + baselineVersion + "," + baselineDescription + ") as it has already been baselined with (" + baselineMarker.getVersion() + "," + baselineMarker.getDescription() + ")\n" + "Need to reset your baseline? Learn more: " + FlywayDbWebsiteLinks.RESET_THE_BASELINE_MIGRATION);
}
} else {
if (schemaHistory.hasSchemasMarker() && baselineVersion.equals(MigrationVersion.fromVersion("0"))) {
throw new FlywayException("Unable to baseline schema history table " + schemaHistory + " with version 0 as this version was used for schema creation");
}
if (schemaHistory.hasNonSyntheticAppliedMigrations()) {
throw new FlywayException("Unable to baseline schema history table " + schemaHistory + " as it already contains migrations\n" + "Need to reset your baseline? Learn more: " + FlywayDbWebsiteLinks.RESET_THE_BASELINE_MIGRATION);
}
if (schemaHistory.allAppliedMigrations().isEmpty()) {
throw new FlywayException("Unable to baseline schema history table " + schemaHistory + " as it already exists, and is empty.\n" + "Delete the schema history table with the clean command, and run baseline again.");
}
throw new FlywayException("Unable to baseline schema history table " + schemaHistory + " as it already contains migrations.\n" + "Delete the schema history table with the clean command, and run baseline again.\n" + "Need to reset your baseline? Learn more: " + FlywayDbWebsiteLinks.RESET_THE_BASELINE_MIGRATION);
}
}
} catch (FlywayException e) {
callbackExecutor.onEvent(Event.AFTER_BASELINE_ERROR);
baselineResult.successfullyBaselined = false;
throw e;
}
callbackExecutor.onEvent(Event.AFTER_BASELINE);
return baselineResult;
}
use of org.flywaydb.core.internal.schemahistory.AppliedMigration in project flyway by flyway.
the class DbRepair method alignAppliedMigrationsWithResolvedMigrations.
private boolean alignAppliedMigrationsWithResolvedMigrations() {
boolean repaired = false;
for (MigrationInfo migrationInfo : migrationInfoService.all()) {
MigrationInfoImpl migrationInfoImpl = (MigrationInfoImpl) migrationInfo;
ResolvedMigration resolved = migrationInfoImpl.getResolvedMigration();
AppliedMigration applied = migrationInfoImpl.getAppliedMigration();
// Repair versioned
if (resolved != null && resolved.getVersion() != null && applied != null && !applied.getType().isSynthetic() && migrationInfoImpl.getState() != MigrationState.IGNORED && updateNeeded(resolved, applied)) {
schemaHistory.update(applied, resolved);
repaired = true;
repairResult.migrationsAligned.add(CommandResultFactory.createRepairOutput(migrationInfo));
}
// Repair repeatable
if (resolved != null && resolved.getVersion() == null && applied != null && !applied.getType().isSynthetic() && migrationInfoImpl.getState() != MigrationState.IGNORED && resolved.checksumMatchesWithoutBeingIdentical(applied.getChecksum())) {
schemaHistory.update(applied, resolved);
repaired = true;
repairResult.migrationsAligned.add(CommandResultFactory.createRepairOutput(migrationInfo));
}
}
return repaired;
}
use of org.flywaydb.core.internal.schemahistory.AppliedMigration in project flyway by flyway.
the class DbRepair method deleteMissingMigrations.
private boolean deleteMissingMigrations() {
boolean removed = false;
for (MigrationInfo migrationInfo : migrationInfoService.all()) {
MigrationInfoImpl migrationInfoImpl = (MigrationInfoImpl) migrationInfo;
if (migrationInfo.getType().isSynthetic()) {
continue;
}
AppliedMigration applied = migrationInfoImpl.getAppliedMigration();
MigrationState state = migrationInfoImpl.getState();
boolean isMigrationMissing = state == MigrationState.MISSING_SUCCESS || state == MigrationState.MISSING_FAILED || state == MigrationState.FUTURE_SUCCESS || state == MigrationState.FUTURE_FAILED;
boolean isMigrationIgnored = Arrays.stream(configuration.getIgnoreMigrationPatterns()).anyMatch(p -> p.matchesMigration(migrationInfoImpl.getVersion() != null, state));
if (isMigrationMissing && !isMigrationIgnored) {
schemaHistory.delete(applied);
removed = true;
repairResult.migrationsDeleted.add(CommandResultFactory.createRepairOutput(migrationInfo));
}
}
return removed;
}
Aggregations