11import 'package:drift/drift.dart' ;
2+ import 'package:drift/internal/versioned_schema.dart' ;
23import 'package:drift/remote.dart' ;
34import 'package:sqlite3/common.dart' ;
45
6+ import '../log.dart' ;
57import 'schema_versions.g.dart' ;
68
79part 'database.g.dart' ;
@@ -49,6 +51,19 @@ class UriConverter extends TypeConverter<Uri, String> {
4951 @override Uri fromSql (String fromDb) => Uri .parse (fromDb);
5052}
5153
54+ // TODO(upstream): generate this
55+ VersionedSchema _getSchema ({
56+ required DatabaseConnectionUser database,
57+ required int schemaVersion,
58+ }) {
59+ switch (schemaVersion) {
60+ case 2 :
61+ return Schema2 (database: database);
62+ default :
63+ throw Exception ('unknown schema version: $schemaVersion ' );
64+ }
65+ }
66+
5267@DriftDatabase (tables: [Accounts ])
5368class AppDatabase extends _$AppDatabase {
5469 AppDatabase (super .e);
@@ -65,6 +80,31 @@ class AppDatabase extends _$AppDatabase {
6580 @override
6681 int get schemaVersion => 2 ; // See note.
6782
83+ Future <void > _dropAndCreateAll (Migrator m, {
84+ required int schemaVersion,
85+ }) async {
86+ await m.database.transaction (() async {
87+ final query = m.database.customSelect (
88+ "SELECT name FROM sqlite_master WHERE type='table'" );
89+ for (final row in await query.get ()) {
90+ final data = row.data;
91+ final tableName = data['name' ] as String ;
92+ // Skip sqlite-internal tables. See for comparison:
93+ // https://www.sqlite.org/fileformat2.html#intschema
94+ // https://github.com/simolus3/drift/blob/0901c984a/drift_dev/lib/src/services/schema/verifier_common.dart#L9-L22
95+ if (tableName.startsWith ('sqlite_' )) continue ;
96+ // No need to worry about SQL injection; this table name
97+ // was already a table name in the database, not something
98+ // that should be affected by user data.
99+ await m.database.customStatement ('DROP TABLE $tableName ' );
100+ }
101+ final schema = _getSchema (database: m.database, schemaVersion: schemaVersion);
102+ for (final entity in schema.entities) {
103+ await m.create (entity);
104+ }
105+ });
106+ }
107+
68108 @override
69109 MigrationStrategy get migration {
70110 return MigrationStrategy (
@@ -73,15 +113,11 @@ class AppDatabase extends _$AppDatabase {
73113 },
74114 onUpgrade: (Migrator m, int from, int to) async {
75115 if (from > to) {
76- // TODO(log): log schema downgrade as an error
77116 // This should only ever happen in dev. As a dev convenience,
78117 // drop everything from the database and start over.
79- for (final entity in allSchemaEntities) {
80- // This will miss any entire tables (or indexes, etc.) that
81- // don't exist at this version. For a dev-only feature, that's OK.
82- await m.drop (entity);
83- }
84- await m.createAll ();
118+ // TODO(log): log schema downgrade as an error
119+ assert (debugLog ('Downgrading schema from v$from to v$to .' ));
120+ await _dropAndCreateAll (m, schemaVersion: to);
85121 return ;
86122 }
87123 assert (1 <= from && from <= to && to <= schemaVersion);
0 commit comments