Fix preUpdateSchema to support multiple version steps

The preUpdateSchema method ran too late when declared in schema
version 81 and the installation was updating from version 79 through
80 to 81.  During the 79->80 step gwtorm created missing tables and
columns, failing to give version 81's preUpdateSchema method a chance
to rename tables and columns from an old name to a new name.

Run all intermediate preUpdateSchema methods before running the gwtorm
black magic, then run migrateData after all current columns and tables
are in place.

Change-Id: Id5a9b5c7f39bd0e25a38cad37abaea2c7077a6ca
This commit is contained in:
Shawn Pearce
2013-08-12 14:24:43 -07:00
parent 61c3cf69f7
commit adf540382b
3 changed files with 57 additions and 44 deletions

View File

@@ -61,7 +61,7 @@ public class SchemaUpdater {
} else {
try {
u.check(ui, version, db, true);
u.check(ui, version, db);
} catch (SQLException e) {
throw new OrmException("Cannot upgrade schema", e);
}

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.schema;
import com.google.common.collect.Lists;
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.jdbc.JdbcExecutor;
@@ -25,7 +26,6 @@ import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -68,59 +68,83 @@ public abstract class SchemaVersion {
return versionNbr;
}
public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db, boolean toTargetVersion)
public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
throws OrmException, SQLException {
if (curr.versionNbr == versionNbr) {
// Nothing to do, we are at the correct schema.
//
} else if (curr.versionNbr > versionNbr) {
throw new OrmException("Cannot downgrade database schema from version "
+ curr.versionNbr + " to " + versionNbr + ".");
} else {
upgradeFrom(ui, curr, db, toTargetVersion);
upgradeFrom(ui, curr, db);
}
}
/** Runs check on the prior schema version, and then upgrades. */
protected void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db, boolean toTargetVersion)
private void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
throws OrmException, SQLException {
final JdbcSchema s = (JdbcSchema) db;
List<SchemaVersion> pending = pending(curr.versionNbr);
updateSchema(pending, ui, db);
migrateData(pending, ui, curr, db);
if (curr.versionNbr > versionNbr) {
throw new OrmException("Cannot downgrade database schema from version " + curr.versionNbr
+ " to " + versionNbr + ".");
}
prior.get().check(ui, curr, db, false);
ui.message("Upgrading database schema from version " + curr.versionNbr
+ " to " + versionNbr + " ...");
preUpdateSchema(db);
final JdbcExecutor e = new JdbcExecutor(s);
JdbcSchema s = (JdbcSchema) db;
JdbcExecutor e = new JdbcExecutor(s);
try {
s.updateSchema(e);
migrateData(db, ui);
if (toTargetVersion) {
final List<String> pruneList = new ArrayList<String>();
s.pruneSchema(new StatementExecutor() {
public void execute(String sql) {
pruneList.add(sql);
}
});
if (!pruneList.isEmpty()) {
ui.pruneSchema(e, pruneList);
final List<String> pruneList = Lists.newArrayList();
s.pruneSchema(new StatementExecutor() {
public void execute(String sql) {
pruneList.add(sql);
}
});
if (!pruneList.isEmpty()) {
ui.pruneSchema(e, pruneList);
}
} finally {
e.close();
}
finish(curr, db);
}
private List<SchemaVersion> pending(int curr) {
List<SchemaVersion> r = Lists.newArrayListWithCapacity(versionNbr - curr);
for (SchemaVersion v = this; curr < v.getVersionNbr(); v = v.prior.get()) {
r.add(v);
}
Collections.reverse(r);
return r;
}
private void updateSchema(List<SchemaVersion> pending, UpdateUI ui,
ReviewDb db) throws OrmException, SQLException {
for (SchemaVersion v : pending) {
ui.message(String.format("Upgrading schema to %d ...", v.getVersionNbr()));
v.preUpdateSchema(db);
}
JdbcSchema s = (JdbcSchema) db;
JdbcExecutor e = new JdbcExecutor(s);
try {
s.updateSchema(e);
} finally {
e.close();
}
}
/** Invoke before updateSchema adds new columns/tables. */
protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {
}
private void migrateData(List<SchemaVersion> pending, UpdateUI ui,
CurrentSchemaVersion curr, ReviewDb db) throws OrmException, SQLException {
for (SchemaVersion v : pending) {
ui.message(String.format(
"Migrating data to schema %d ...",
v.getVersionNbr()));
v.migrateData(db, ui);
v.finish(curr, db);
}
}
/**
* Invoked between updateSchema (adds new columns/tables) and pruneSchema
* (removes deleted columns/tables).

View File

@@ -14,9 +14,6 @@
package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
@@ -30,12 +27,4 @@ public class Schema_52 extends SchemaVersion {
}
});
}
@Override
protected void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr,
ReviewDb db, boolean toTargetVersion) throws OrmException {
throw new OrmException("Cannot upgrade from schema " + curr.versionNbr
+ "; manually run init from Gerrit Code Review 2.1.7"
+ " and restart this version to continue.");
}
}