Skip to content

Commit 6007324

Browse files
authored
Merge pull request #125 from harawata/123-skipped-migration
Print warnings when there is a skipped migration or a missing migration script.
2 parents 43a2ac0 + 412052e commit 6007324

File tree

7 files changed

+101
-44
lines changed

7 files changed

+101
-44
lines changed

src/main/java/org/apache/ibatis/migration/operations/DatabaseOperation.java

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010-2017 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,11 +46,6 @@ protected void insertChangelog(Change change, ConnectionProvider connectionProvi
4646
}
4747
}
4848

49-
protected Change getLastAppliedChange(ConnectionProvider connectionProvider, DatabaseOperationOption option) {
50-
List<Change> changelog = getChangelog(connectionProvider, option);
51-
return changelog.isEmpty() ? null : changelog.get(changelog.size() - 1);
52-
}
53-
5449
protected List<Change> getChangelog(ConnectionProvider connectionProvider, DatabaseOperationOption option) {
5550
SqlRunner runner = getSqlRunner(connectionProvider);
5651
try {
@@ -83,6 +78,27 @@ protected boolean changelogExists(ConnectionProvider connectionProvider, Databas
8378
}
8479
}
8580

81+
protected void checkSkippedOrMissing(List<Change> changesInDb, List<Change> migrations, PrintStream printStream) {
82+
int adjust = 0;
83+
for (int i = 0; i < changesInDb.size(); i++) {
84+
Change changeInDb = changesInDb.get(i);
85+
int migrationIndex = migrations.indexOf(changeInDb);
86+
if (migrationIndex == -1) {
87+
// no corresponding migration script.
88+
println(printStream, "WARNING: Missing migration script. id='" + changeInDb.getId() + "', description='"
89+
+ changeInDb.getDescription() + "'.");
90+
adjust++;
91+
} else if (migrationIndex != (i - adjust)) {
92+
// Unapplied migration script(s).
93+
for (int j = i - adjust; j < migrationIndex; j++) {
94+
adjust--;
95+
println(printStream,
96+
"WARNING: Migration script '" + migrations.get(j).getFilename() + "' was not applied to the database.");
97+
}
98+
}
99+
}
100+
}
101+
86102
protected SqlRunner getSqlRunner(ConnectionProvider connectionProvider) {
87103
try {
88104
return new SqlRunner(connectionProvider.getConnection());

src/main/java/org/apache/ibatis/migration/operations/DownOperation.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010-2017 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,12 +56,16 @@ public DownOperation operate(ConnectionProvider connectionProvider, MigrationLoa
5656
if (option == null) {
5757
option = new DatabaseOperationOption();
5858
}
59-
Change lastChange = getLastAppliedChange(connectionProvider, option);
60-
if (lastChange == null) {
59+
List<Change> changesInDb = Collections.emptyList();
60+
if (changelogExists(connectionProvider, option)) {
61+
changesInDb = getChangelog(connectionProvider, option);
62+
}
63+
if (changesInDb.isEmpty()) {
6164
println(printStream, "Changelog exist, but no migration found.");
6265
} else {
6366
List<Change> migrations = migrationsLoader.getMigrations();
6467
Collections.sort(migrations);
68+
checkSkippedOrMissing(changesInDb, migrations, printStream);
6569
Collections.reverse(migrations);
6670
int stepCount = 0;
6771
ScriptRunner runner = getScriptRunner(connectionProvider, option, printStream);
@@ -70,7 +74,7 @@ public DownOperation operate(ConnectionProvider connectionProvider, MigrationLoa
7074

7175
try {
7276
for (Change change : migrations) {
73-
if (change.getId().equals(lastChange.getId())) {
77+
if (change.equals(changesInDb.get(changesInDb.size() - 1))) {
7478
if (stepCount == 0 && hook != null) {
7579
hookBindings.put(MigrationHook.HOOK_CONTEXT, new HookContext(connectionProvider, runner, null));
7680
hook.before(hookBindings);
@@ -99,7 +103,7 @@ public DownOperation operate(ConnectionProvider connectionProvider, MigrationLoa
99103
if (steps == null || stepCount >= steps) {
100104
break;
101105
}
102-
lastChange = getLastAppliedChange(connectionProvider, option);
106+
changesInDb.remove(changesInDb.size() - 1);
103107
}
104108
}
105109
if (stepCount > 0 && hook != null) {

src/main/java/org/apache/ibatis/migration/operations/UpOperation.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010-2017 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,13 +61,14 @@ public UpOperation operate(ConnectionProvider connectionProvider, MigrationLoade
6161
option = new DatabaseOperationOption();
6262
}
6363

64-
Change lastChange = null;
64+
List<Change> changesInDb = Collections.emptyList();
6565
if (changelogExists(connectionProvider, option)) {
66-
lastChange = getLastAppliedChange(connectionProvider, option);
66+
changesInDb = getChangelog(connectionProvider, option);
6767
}
6868

6969
List<Change> migrations = migrationsLoader.getMigrations();
7070
Collections.sort(migrations);
71+
checkSkippedOrMissing(changesInDb, migrations, printStream);
7172
int stepCount = 0;
7273
ScriptRunner runner = getScriptRunner(connectionProvider, option, printStream);
7374

@@ -77,7 +78,7 @@ public UpOperation operate(ConnectionProvider connectionProvider, MigrationLoade
7778
Reader onAbortScriptReader = null;
7879
try {
7980
for (Change change : migrations) {
80-
if (lastChange == null || change.getId().compareTo(lastChange.getId()) > 0) {
81+
if (changesInDb.isEmpty() || change.compareTo(changesInDb.get(changesInDb.size() - 1)) > 0) {
8182
if (stepCount == 0 && hook != null) {
8283
hookBindings.put(MigrationHook.HOOK_CONTEXT, new HookContext(connectionProvider, runner, null));
8384
hook.before(hookBindings);

src/main/java/org/apache/ibatis/migration/operations/VersionOperation.java

+22-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010-2017 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,33 +47,35 @@ public VersionOperation operate(ConnectionProvider connectionProvider, Migration
4747
if (option == null) {
4848
option = new DatabaseOperationOption();
4949
}
50-
ensureVersionExists(migrationsLoader);
51-
Change change = getLastAppliedChange(connectionProvider, option);
52-
if (change == null || version.compareTo(change.getId()) > 0) {
50+
List<Change> changesInDb = getChangelog(connectionProvider, option);
51+
List<Change> migrations = migrationsLoader.getMigrations();
52+
Change specified = new Change(version);
53+
if (!migrations.contains(specified)) {
54+
throw new MigrationException("A migration for the specified version number does not exist.");
55+
}
56+
Change lastChangeInDb = changesInDb.isEmpty() ? null : changesInDb.get(changesInDb.size() - 1);
57+
if (lastChangeInDb == null || specified.compareTo(lastChangeInDb) > 0) {
5358
println(printStream, "Upgrading to: " + version);
54-
UpOperation up = new UpOperation(1);
55-
while (!version.equals(change.getId())) {
56-
up.operate(connectionProvider, migrationsLoader, option, printStream, upHook);
57-
change = getLastAppliedChange(connectionProvider, option);
59+
int steps = 0;
60+
for (Change change : migrations) {
61+
if (change.compareTo(lastChangeInDb) > 0 && change.compareTo(specified) < 1) {
62+
steps++;
63+
}
5864
}
59-
} else if (version.compareTo(change.getId()) < 0) {
65+
new UpOperation(steps).operate(connectionProvider, migrationsLoader, option, printStream, upHook);
66+
} else if (specified.compareTo(lastChangeInDb) < 0) {
6067
println(printStream, "Downgrading to: " + version);
61-
DownOperation down = new DownOperation(1);
62-
while (!version.equals(change.getId())) {
63-
down.operate(connectionProvider, migrationsLoader, option, printStream, downHook);
64-
change = getLastAppliedChange(connectionProvider, option);
68+
int steps = 0;
69+
for (Change change : migrations) {
70+
if (change.compareTo(specified) > -1 && change.compareTo(lastChangeInDb) < 0) {
71+
steps++;
72+
}
6573
}
74+
new DownOperation(steps).operate(connectionProvider, migrationsLoader, option, printStream, downHook);
6675
} else {
6776
println(printStream, "Already at version: " + version);
6877
}
6978
println(printStream);
7079
return this;
7180
}
72-
73-
private void ensureVersionExists(MigrationLoader migrationsLoader) {
74-
List<Change> migrations = migrationsLoader.getMigrations();
75-
if (!migrations.contains(new Change(version))) {
76-
throw new MigrationException("A migration for the specified version number does not exist.");
77-
}
78-
}
7981
}

src/test/java/org/apache/ibatis/migration/MigratorTest.java

+41-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010-2017 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -80,6 +80,8 @@ public void checkAssertion() {
8080

8181
testVersionCommand();
8282
testStatusContainsNoPendingMigrations();
83+
testSkippedScript();
84+
testMissingScript();
8385
testDownCommand();
8486
testStatusContainsPendingMigrations();
8587
testPendingCommand();
@@ -153,11 +155,43 @@ private void testDoPendingScriptCommand() throws Exception {
153155

154156
private void testVersionCommand() throws Exception {
155157
out.clearLog();
156-
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "version", "20080827200216"));
158+
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "version", "20080827200217"));
157159
String output = out.getLog();
158160
assertFalse(output.toString().contains("FAILURE"));
159161
}
160162

163+
private void testSkippedScript() throws Exception {
164+
out.clearLog();
165+
File skipped = new File(dir + File.separator + "scripts", "20080827200215_skipped_migration.sql");
166+
assertTrue(skipped.createNewFile());
167+
try {
168+
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "up"));
169+
String output = out.getLog();
170+
assertFalse(output.toString().contains("FAILURE"));
171+
assertEquals(1, TestUtil.countStr(output, "WARNING"));
172+
assertTrue(output.toString().contains(
173+
"WARNING: Migration script '20080827200215_skipped_migration.sql' was not applied to the database."));
174+
} finally {
175+
skipped.delete();
176+
}
177+
}
178+
179+
private void testMissingScript() throws Exception {
180+
out.clearLog();
181+
File original = new File(dir + File.separator + "scripts", "20080827200216_create_procs.sql");
182+
File renamed = new File(dir + File.separator + "scripts", "20080827200216_create_procs._sql");
183+
assertTrue(original.renameTo(renamed));
184+
try {
185+
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "up"));
186+
String output = out.getLog();
187+
assertFalse(output.toString().contains("FAILURE"));
188+
assertTrue(output.toString()
189+
.contains("WARNING: Missing migration script. id='20080827200216', description='create procs'."));
190+
} finally {
191+
assertTrue(renamed.renameTo(original));
192+
}
193+
}
194+
161195
private void testDownCommand() throws Exception {
162196
out.clearLog();
163197
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "down"));
@@ -206,7 +240,7 @@ private void testDoScriptCommand() throws Exception {
206240
assertFalse(output.toString().contains("20080827200212"));
207241
assertTrue(output.toString().contains("20080827200213"));
208242
assertTrue(output.toString().contains("20080827200214"));
209-
assertFalse(output.toString().contains("20080827200215"));
243+
assertFalse(output.toString().contains("20080827200216"));
210244
assertFalse(output.toString().contains("-- @UNDO"));
211245

212246
out.clearLog();
@@ -218,21 +252,21 @@ private void testDoScriptCommand() throws Exception {
218252
assertFalse(output.toString().contains("20080827200212"));
219253
assertFalse(output.toString().contains("20080827200213"));
220254
assertFalse(output.toString().contains("20080827200214"));
221-
assertFalse(output.toString().contains("20080827200215"));
255+
assertFalse(output.toString().contains("20080827200216"));
222256
assertFalse(output.toString().contains("-- @UNDO"));
223257
}
224258

225259
private void testUndoScriptCommand() throws Exception {
226260
out.clearLog();
227-
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "script", "20080827200215", "20080827200213"));
261+
Migrator.main(TestUtil.args("--path=" + dir.getAbsolutePath(), "script", "20080827200216", "20080827200213"));
228262
String output = out.getLog();
229263
assertFalse(output.toString().contains("FAILURE"));
230264
assertFalse(output.toString().contains("20080827200210"));
231265
assertFalse(output.toString().contains("20080827200211"));
232266
assertFalse(output.toString().contains("20080827200212"));
233267
assertFalse(output.toString().contains("20080827200213"));
234268
assertTrue(output.toString().contains("20080827200214"));
235-
assertTrue(output.toString().contains("20080827200215"));
269+
assertTrue(output.toString().contains("20080827200216"));
236270
assertTrue(output.toString().contains("-- @UNDO"));
237271
out.clearLog();
238272

@@ -244,7 +278,7 @@ private void testUndoScriptCommand() throws Exception {
244278
assertFalse(output.toString().contains("20080827200212"));
245279
assertFalse(output.toString().contains("20080827200213"));
246280
assertFalse(output.toString().contains("20080827200214"));
247-
assertFalse(output.toString().contains("20080827200215"));
281+
assertFalse(output.toString().contains("20080827200216"));
248282
assertTrue(output.toString().contains("-- @UNDO"));
249283
}
250284

src/test/java/org/apache/ibatis/migration/example/scripts/20080827200215_create_procs.sql renamed to src/test/java/org/apache/ibatis/migration/example/scripts/20080827200216_create_procs.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright 2010-2016 the original author or authors.
2+
-- Copyright 2010-2018 the original author or authors.
33
--
44
-- Licensed under the Apache License, Version 2.0 (the "License");
55
-- you may not use this file except in compliance with the License.
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright 2010-2016 the original author or authors.
2+
-- Copyright 2010-2018 the original author or authors.
33
--
44
-- Licensed under the Apache License, Version 2.0 (the "License");
55
-- you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)