Skip to content

Commit df7e41c

Browse files
committed
db: Drop all tables on downgrade
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]>
1 parent 52fb7a4 commit df7e41c

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

Diff for: lib/model/database.dart

+21-8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ class AppDatabase extends _$AppDatabase {
6363
@override
6464
int get schemaVersion => 2; // See note.
6565

66+
Future<void> _resetDatabase(Migrator m) async {
67+
// This should only ever happen in dev. As a dev convenience,
68+
// drop everything from the database and start over.
69+
await m.database.transaction(() async {
70+
final query = m.database.customSelect(
71+
"SELECT name FROM sqlite_master WHERE type='table'");
72+
for (final row in await query.get()) {
73+
final data = row.data;
74+
final tableName = data['name'] as String;
75+
// Skip sqlite-internal tables, https://www.sqlite.org/fileformat2.html#intschema
76+
// https://github.com/simolus3/drift/blob/0901c984a987e54ba0b67e227adbfdcf3c08eeb4/drift_dev/lib/src/services/schema/verifier_common.dart#L9-L22
77+
if (tableName.startsWith('sqlite_')) continue;
78+
// SQL injection could be a concern, but the database would've been
79+
// compromised if the table name is corrupted.
80+
await m.database.customStatement('DROP TABLE $tableName');
81+
}
82+
await m.createAll();
83+
});
84+
}
85+
6686
@override
6787
MigrationStrategy get migration {
6888
return MigrationStrategy(
@@ -72,14 +92,7 @@ class AppDatabase extends _$AppDatabase {
7292
onUpgrade: (Migrator m, int from, int to) async {
7393
if (from > to) {
7494
// TODO(log): log schema downgrade as an error
75-
// This should only ever happen in dev. As a dev convenience,
76-
// drop everything from the database and start over.
77-
for (final entity in allSchemaEntities) {
78-
// This will miss any entire tables (or indexes, etc.) that
79-
// don't exist at this version. For a dev-only feature, that's OK.
80-
await m.drop(entity);
81-
}
82-
await m.createAll();
95+
await _resetDatabase(m);
8396
return;
8497
}
8598
assert(1 <= from && from <= to && to <= schemaVersion);

0 commit comments

Comments
 (0)