Skip to content

Commit

Permalink
db: Drop all tables on downgrade
Browse files Browse the repository at this point in the history
We previously missed tables that are not known to the schema.  This
becomes an issue if a new table is added at a newer schema level. When
we go back to an earlier schema, that new table remains in the database,
so subsequent attempts to upgrade to the later schema level that adds
the table will fail, because it already exists.

Testing for this is blocked until #1172.

Signed-off-by: Zixuan James Li <[email protected]>
  • Loading branch information
PIG208 committed Jan 3, 2025
1 parent a7b1456 commit ebac46b
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions lib/model/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ class AppDatabase extends _$AppDatabase {
@override
int get schemaVersion => 2; // See note.

Future<void> _resetDatabase(Migrator m) async {
// This should only ever happen in dev. As a dev convenience,
// drop everything from the database and start over.
await m.database.transaction(() async {
final query = m.database.customSelect(
"SELECT name FROM sqlite_master WHERE type='table'");
for (final row in await query.get()) {
final data = row.data;
final tableName = data['name'] as String;
// Skip sqlite-internal tables, https://www.sqlite.org/fileformat2.html#intschema
// https://github.com/simolus3/drift/blob/0901c984a987e54ba0b67e227adbfdcf3c08eeb4/drift_dev/lib/src/services/schema/verifier_common.dart#L9-L22
if (tableName.startsWith('sqlite_')) continue;
// SQL injection could be a concern, but the database would've been
// compromised if the table name is corrupted.
await m.database.customStatement('DROP TABLE $tableName');
}
await m.createAll();
});
}

@override
MigrationStrategy get migration {
return MigrationStrategy(
Expand All @@ -72,14 +92,7 @@ class AppDatabase extends _$AppDatabase {
onUpgrade: (Migrator m, int from, int to) async {
if (from > to) {
// TODO(log): log schema downgrade as an error
// This should only ever happen in dev. As a dev convenience,
// drop everything from the database and start over.
for (final entity in allSchemaEntities) {
// This will miss any entire tables (or indexes, etc.) that
// don't exist at this version. For a dev-only feature, that's OK.
await m.drop(entity);
}
await m.createAll();
await _resetDatabase(m);
return;
}
assert(1 <= from && from <= to && to <= schemaVersion);
Expand Down

0 comments on commit ebac46b

Please sign in to comment.