mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Apply more than one migration if suitable.
This commit is contained in:
@@ -311,7 +311,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (!checkSchemaVersion(txn)) throw new DbException();
|
||||
} else {
|
||||
createTables(txn);
|
||||
storeSchemaVersion(txn);
|
||||
storeSchemaVersion(txn, CODE_SCHEMA_VERSION);
|
||||
}
|
||||
createIndexes(txn);
|
||||
commitTransaction(txn);
|
||||
@@ -327,31 +327,31 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (dataSchemaVersion == -1) return false;
|
||||
if (dataSchemaVersion == CODE_SCHEMA_VERSION) return true;
|
||||
if (CODE_SCHEMA_VERSION < dataSchemaVersion) return false;
|
||||
// Do we have a suitable migration?
|
||||
// Apply any suitable migrations in order
|
||||
for (Migration<Connection> m : getMigrations()) {
|
||||
int start = m.getStartVersion(), end = m.getEndVersion();
|
||||
if (start == dataSchemaVersion && end == CODE_SCHEMA_VERSION) {
|
||||
if (start == dataSchemaVersion) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Migrating from schema " + start + " to " + end);
|
||||
// Apply the migration
|
||||
m.migrate(txn);
|
||||
// Store the new schema version
|
||||
storeSchemaVersion(txn);
|
||||
return true;
|
||||
storeSchemaVersion(txn, end);
|
||||
dataSchemaVersion = end;
|
||||
}
|
||||
}
|
||||
// No suitable migration
|
||||
return false;
|
||||
return dataSchemaVersion == CODE_SCHEMA_VERSION;
|
||||
}
|
||||
|
||||
// Package access for testing
|
||||
Collection<Migration<Connection>> getMigrations() {
|
||||
List<Migration<Connection>> getMigrations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void storeSchemaVersion(Connection txn) throws DbException {
|
||||
private void storeSchemaVersion(Connection txn, int version)
|
||||
throws DbException {
|
||||
Settings s = new Settings();
|
||||
s.putInt(SCHEMA_VERSION_KEY, CODE_SCHEMA_VERSION);
|
||||
s.putInt(SCHEMA_VERSION_KEY, version);
|
||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||
@@ -33,14 +34,17 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
private final File testDir = TestUtils.getTestDirectory();
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Migration<Connection> migration =
|
||||
context.mock(Migration.class);
|
||||
context.mock(Migration.class, "migration");
|
||||
@SuppressWarnings("unchecked")
|
||||
private final Migration<Connection> migration1 =
|
||||
context.mock(Migration.class, "migration1");
|
||||
|
||||
protected final DatabaseConfig config =
|
||||
new TestDatabaseConfig(testDir, 1024 * 1024);
|
||||
protected final Clock clock = new SystemClock();
|
||||
|
||||
abstract Database<Connection> createDatabase(
|
||||
Collection<Migration<Connection>> migrations) throws Exception;
|
||||
List<Migration<Connection>> migrations) throws Exception;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -65,14 +69,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
public void testThrowsExceptionIfDataSchemaVersionIsMissing()
|
||||
throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, -1);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(singletonList(migration));
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open();
|
||||
}
|
||||
|
||||
@@ -80,12 +84,12 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
public void testDoesNotRunMigrationsIfSchemaVersionsMatch()
|
||||
throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
// Reopen the DB - migrations should not be run
|
||||
db = createDatabase(singletonList(migration));
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
@@ -94,14 +98,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
@Test(expected = DbException.class)
|
||||
public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(singletonList(migration));
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open();
|
||||
}
|
||||
|
||||
@@ -126,18 +130,22 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
oneOf(migration).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 2));
|
||||
oneOf(migration).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
oneOf(migration1).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
oneOf(migration1).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION));
|
||||
}});
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1);
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(singletonList(migration));
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open();
|
||||
}
|
||||
|
||||
@@ -145,22 +153,62 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
public void testRunsMigrationIfCodeIsNewerThanDataAndSuitableMigration()
|
||||
throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
// First migration should be run, increasing schema version by 2
|
||||
oneOf(migration).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 2));
|
||||
oneOf(migration).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION));
|
||||
oneOf(migration).migrate(with(any(Connection.class)));
|
||||
// Second migration is not suitable and should be skipped
|
||||
oneOf(migration1).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
oneOf(migration1).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION));
|
||||
}});
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1);
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||
db.close();
|
||||
// Reopen the DB - the migration should be run
|
||||
db = createDatabase(singletonList(migration));
|
||||
// Reopen the DB - the first migration should be run
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRunsMigrationsIfCodeIsNewerThanDataAndSuitableMigrations()
|
||||
throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
// First migration should be run, incrementing schema version
|
||||
oneOf(migration).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 2));
|
||||
oneOf(migration).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
oneOf(migration).migrate(with(any(Connection.class)));
|
||||
// Second migration should be run, incrementing schema version again
|
||||
oneOf(migration1).getStartVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION - 1));
|
||||
oneOf(migration1).getEndVersion();
|
||||
will(returnValue(CODE_SCHEMA_VERSION));
|
||||
oneOf(migration1).migrate(with(any(Connection.class)));
|
||||
}});
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||
db.close();
|
||||
// Reopen the DB - both migrations should be run
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open());
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@ package org.briarproject.bramble.db;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@NotNullByDefault
|
||||
public class H2MigrationTest extends DatabaseMigrationTest {
|
||||
|
||||
@Override
|
||||
Database<Connection> createDatabase(
|
||||
Collection<Migration<Connection>> migrations) throws Exception {
|
||||
Database<Connection> createDatabase(List<Migration<Connection>> migrations)
|
||||
throws Exception {
|
||||
return new H2Database(config, clock) {
|
||||
@Override
|
||||
Collection<Migration<Connection>> getMigrations() {
|
||||
List<Migration<Connection>> getMigrations() {
|
||||
return migrations;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,17 +3,17 @@ package org.briarproject.bramble.db;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@NotNullByDefault
|
||||
public class HyperSqlMigrationTest extends DatabaseMigrationTest {
|
||||
|
||||
@Override
|
||||
Database<Connection> createDatabase(
|
||||
Collection<Migration<Connection>> migrations) throws Exception {
|
||||
Database<Connection> createDatabase(List<Migration<Connection>> migrations)
|
||||
throws Exception {
|
||||
return new HyperSqlDatabase(config, clock) {
|
||||
@Override
|
||||
Collection<Migration<Connection>> getMigrations() {
|
||||
List<Migration<Connection>> getMigrations() {
|
||||
return migrations;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user