77
88import java .sql .Connection ;
99import java .sql .SQLException ;
10- import java .util .Collections ;
1110import java .util .List ;
12- import java .util .Map ;
13- import java .util .stream .Collectors ;
1411
1512import static java .lang .System .Logger .Level .*;
1613import static java .lang .System .Logger .Level .WARNING ;
14+ import static java .util .Collections .emptyList ;
1715
1816/**
1917 * Actually runs the migrations.
@@ -25,8 +23,6 @@ public class MigrationEngine {
2523 private final MigrationConfig migrationConfig ;
2624 private final boolean checkStateOnly ;
2725 private final boolean fastMode ;
28- private int fastModeCount ;
29- private MigrationTable table ;
3026
3127 /**
3228 * Create with the MigrationConfig.
@@ -42,23 +38,25 @@ public MigrationEngine(MigrationConfig migrationConfig, boolean checkStateOnly)
4238 */
4339 public List <MigrationResource > run (Connection connection ) {
4440 try {
41+ long startMs = System .currentTimeMillis ();
4542 LocalMigrationResources resources = new LocalMigrationResources (migrationConfig );
4643 if (!resources .readResources () && !resources .readInitResources ()) {
4744 log .log (DEBUG , "no migrations to check" );
48- return Collections . emptyList ();
45+ return emptyList ();
4946 }
50- long startMs = System .currentTimeMillis ();
51- setAutoCommitFalse (connection );
52- table = initMigrationTable (connection );
53- if (fastMode && fastModeCheck (resources .versions ())) {
47+ final var platform = derivePlatform (migrationConfig , connection );
48+ final var firstCheck = new FirstCheck (migrationConfig , connection , platform );
49+ if (fastMode && firstCheck .fastModeCheck (resources .versions ())) {
5450 long checkMs = System .currentTimeMillis () - startMs ;
55- log .log (INFO , "DB migrations completed in {0}ms - totalMigrations:{1}" , checkMs , fastModeCount );
56- return Collections . emptyList ();
51+ log .log (INFO , "DB migrations completed in {0}ms - totalMigrations:{1}" , checkMs , firstCheck . count () );
52+ return emptyList ();
5753 }
54+ // ensure running with autoCommit false
55+ setAutoCommitFalse (connection );
5856
59- initialiseMigrationTable (connection );
57+ final MigrationTable table = initialiseMigrationTable (firstCheck , connection );
6058 try {
61- List <MigrationResource > result = runMigrations (resources .versions ());
59+ List <MigrationResource > result = runMigrations (table , resources .versions ());
6260 connection .commit ();
6361 if (!checkStateOnly ) {
6462 long commitMs = System .currentTimeMillis ();
@@ -92,57 +90,11 @@ private static void setAutoCommitFalse(Connection connection) {
9290 }
9391 }
9492
95- private MigrationTable initMigrationTable (Connection connection ) {
96- final MigrationPlatform platform = derivePlatformName (migrationConfig , connection );
97- return new MigrationTable (migrationConfig , connection , checkStateOnly , platform );
98- }
99-
100- private boolean fastModeCheck (List <LocalMigrationResource > versions ) {
101- try {
102- final List <MigrationMetaRow > rows = table .fastRead ();
103- if (rows .size () != versions .size () + 1 ) {
104- // difference in count of migrations
105- return false ;
106- }
107- final Map <String , Integer > dbChecksums = dbChecksumMap (rows );
108- for (LocalMigrationResource local : versions ) {
109- Integer dbChecksum = dbChecksums .get (local .key ());
110- if (dbChecksum == null ) {
111- // no match, unexpected missing migration
112- return false ;
113- }
114- int localChecksum = checksumFor (local );
115- if (localChecksum != dbChecksum ) {
116- // no match, perhaps repeatable migration change
117- return false ;
118- }
119- }
120- // successful fast check
121- fastModeCount = versions .size ();
122- return true ;
123- } catch (SQLException e ) {
124- // probably migration table does not exist
125- return false ;
126- }
127- }
128-
129- private static Map <String , Integer > dbChecksumMap (List <MigrationMetaRow > rows ) {
130- return rows .stream ().collect (Collectors .toMap (MigrationMetaRow ::version , MigrationMetaRow ::checksum ));
131- }
132-
133- private int checksumFor (LocalMigrationResource local ) {
134- if (local instanceof LocalUriMigrationResource ) {
135- return ((LocalUriMigrationResource )local ).checksum ();
136- } else if (local instanceof LocalDdlMigrationResource ) {
137- return Checksum .calculate (local .content ());
138- } else {
139- return ((LocalJdbcMigrationResource ) local ).checksum ();
140- }
141- }
142-
143- private void initialiseMigrationTable (Connection connection ) {
93+ private MigrationTable initialiseMigrationTable (FirstCheck firstCheck , Connection connection ) {
14494 try {
95+ final MigrationTable table = firstCheck .initTable (checkStateOnly );
14596 table .createIfNeededAndLock ();
97+ return table ;
14698 } catch (Throwable e ) {
14799 rollback (connection );
148100 throw new MigrationException ("Error initialising db migrations table" , e );
@@ -152,7 +104,7 @@ private void initialiseMigrationTable(Connection connection) {
152104 /**
153105 * Run all the migrations as needed.
154106 */
155- private List <MigrationResource > runMigrations (List <LocalMigrationResource > localVersions ) throws SQLException {
107+ private List <MigrationResource > runMigrations (MigrationTable table , List <LocalMigrationResource > localVersions ) throws SQLException {
156108 // get the migrations in version order
157109 if (table .isEmpty ()) {
158110 LocalMigrationResource initVersion = lastInitVersion ();
@@ -182,7 +134,7 @@ private LocalMigrationResource lastInitVersion() {
182134 /**
183135 * Return the platform deriving from connection if required.
184136 */
185- private MigrationPlatform derivePlatformName (MigrationConfig migrationConfig , Connection connection ) {
137+ private MigrationPlatform derivePlatform (MigrationConfig migrationConfig , Connection connection ) {
186138 final String platform = migrationConfig .getPlatform ();
187139 if (platform != null ) {
188140 return DbNameUtil .platform (platform );
0 commit comments