I have a database, here is how I create it:
@UseMoor(tables: [
Users
Images,
], daos: [
UserDao,
ImageDao
])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(FlutterQueryExecutor.inDatabaseFolder(path: 'my-db.sql', logStatements: true));
@override
MigrationStrategy get migration => MigrationStrategy(
beforeOpen: (details) async {
await customStatement('PRAGMA foreign_keys = ON');
},
onUpgrade: (Migrator m, int from, int to) async {
if (from == 1) {
m.createTable(keps);
}
},
);
@override
int get schemaVersion => 2;
}
As you can see first time I had only one table Users
. Later added Images
so I wrote this onUpgrade
method:
onUpgrade: (Migrator m, int from, int to) async {
if (from == 1) {
m.createTable(images);
}
},
Now I want to add one colum to table Users
but I don't know if I should write the onUpgrade
like this:
onUpgrade: (Migrator m, int from, int to) async {
if (from == 1) {
m.createTable(images);
}
else if (from == 2) {
await m.addColumn(users, users.keycloakName);
}
},
);
@override
int get schemaVersion => 3;
In this option I expect the Moor to work like this: if the application on the phone is using a database that has schemaVersion == 2
then it is straightforward: it just adds the column.
But what if the schemaVersion on the phone is 1 and gets a new app version that is using schemaVersion == 3? Does the Moor realize this and first it runs the
if (from == 1) {
m.createTable(images);
}
part, and after it done it runs the:
else if (from == 2) {
await m.addColumn(users, users.keycloakName);
}
part, or I have to write the onUpgrade like this (repeat the code):
onUpgrade: (Migrator m, int from, int to) async {
if (from == 1) {
m.createTable(images);
}
else if (from == 2) {
m.createTable(images);
await m.addColumn(users, users.keycloakName);
}
},
);
@override
int get schemaVersion => 3;
With this the problem that if the schemaVersion was already 2 on the phone, it tries to create the iamges table again...
The onUpgrade
is only run once, so if you're 'upgrading' from 1 to 3, only the first (from == 1
) upgrade will be run, in your code above. You could of course change your code a bit s.t. it will run all upgrades, like
if (from == 1) {
// upgrade from 1, all migrations from 1 to 2 here
m.createTable(images);
}
if (from <= 2) {
// upgrade from 2, all migrations from 2 to 3 here
await m.addColumn(users, users.keycloakName);
}
if (from <= 3) {
// upgrade from 3, all migrations from 3 to 4 here
etc.etc()
}
But as I'm sure you'll understand you need to be very careful how you use this! I personally prefer my above approach to copy-pasting all migrations, but of course it depends on your schema and migrations.
There's actually a very recent discussion about this exact issue in this issue in the Moor repo, so be sure to check that out as well :)