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(drift): 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);
@@ -60,11 +75,37 @@ class AppDatabase extends _$AppDatabase {
6075  //    and generate database code with build_runner. 
6176  //    See ../../README.md#generated-files for more 
6277  //    information on using the build_runner. 
78+   //  * Update [_getSchema] to handle the new schemaVersion. 
6379  //  * Write a migration in `onUpgrade` below. 
6480  //  * Write tests. 
6581  @override 
6682  int  get  schemaVersion =>  2 ; // See note. 
6783
84+   Future <void > _dropAndCreateAll (Migrator  m, {
85+     required  int  schemaVersion,
86+   }) async  {
87+     await  m.database.transaction (() async  {
88+       final  query =  m.database.customSelect (
89+         "SELECT name FROM sqlite_master WHERE type='table'" );
90+       for  (final  row in  await  query.get ()) {
91+         final  data =  row.data;
92+         final  tableName =  data['name' ] as  String ;
93+         // Skip sqlite-internal tables.  See for comparison: 
94+         //   https://www.sqlite.org/fileformat2.html#intschema 
95+         //   https://github.com/simolus3/drift/blob/0901c984a/drift_dev/lib/src/services/schema/verifier_common.dart#L9-L22 
96+         if  (tableName.startsWith ('sqlite_' )) continue ;
97+         // No need to worry about SQL injection; this table name 
98+         // was already a table name in the database, not something 
99+         // that should be affected by user data. 
100+         await  m.database.customStatement ('DROP TABLE $tableName ' );
101+       }
102+       final  schema =  _getSchema (database:  m.database, schemaVersion:  schemaVersion);
103+       for  (final  entity in  schema.entities) {
104+         await  m.create (entity);
105+       }
106+     });
107+   }
108+ 
68109  @override 
69110  MigrationStrategy  get  migration {
70111    return  MigrationStrategy (
@@ -73,15 +114,11 @@ class AppDatabase extends _$AppDatabase {
73114      },
74115      onUpgrade:  (Migrator  m, int  from, int  to) async  {
75116        if  (from >  to) {
76-           // TODO(log): log schema downgrade as an error 
77117          // This should only ever happen in dev.  As a dev convenience, 
78118          // 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 ();
119+           // TODO(log): log schema downgrade as an error 
120+           assert (debugLog ('Downgrading schema from v$from  to v$to .' ));
121+           await  _dropAndCreateAll (m, schemaVersion:  to);
85122          return ;
86123        }
87124        assert (1  <=  from &&  from <=  to &&  to <=  schemaVersion);
0 commit comments