Reputation: 81
I followed this guide Opening an asset database to open an asset database and to copy it to my file system but with "readOnly: true" as I want the user to modify the database inside the app.
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "TEST.db");
var exists = await databaseExists(path);
if (!exists) {
// Should happen only the first time you launch your application
print("Creating new copy from asset");
// Make sure the parent directory exists
try {
await Directory(dirname(path)).create(recursive: true);
} catch (_) {}
// Copy from asset
ByteData data = await rootBundle.load(join("assets", "test.db"));
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
// Write and flush the bytes written
await File(path).writeAsBytes(bytes, flush: true);
} else {
print("Opening existing database");
}
// open the database
return await openDatabase(path, version: 1, onUpgrade: _onUpgrade);
}
And this works perfectly.
But later I want to modify the asset database, e.g. adding new rows, columns or tables or even change the values from a specific already existing column. When I do that I want to update the copied database in the file system with the modified asset database. For that I use onUpgrade.
_onUpgrade(Database db, int oldVersion, int newVersion) async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "TEST.db");
// Delete old database and load new asset database
await deleteDatabase(path);
try {
await Directory(dirname(path)).create(recursive: true);
} catch (_) {}
ByteData data = await rootBundle.load(join("assets", "test.db"));
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await new File(path).writeAsBytes(bytes, flush: true);
// Add new table
// Add new row or column
// Update column
}
I only know how to delete the database in the file system after a version change, but I don't want to delete the changes in the database the user did. How can I merge the new asset database with the database in the file system? How can I add a new table, column or row? And how can I replace a column?
Upvotes: 1
Views: 156
Reputation: 52386
You will have to open it with readOnly = false.
Then when you call onUpgrade you will have to run sql queries to alter the tables with the ALTER TABLE command.
final Future<Database> database = openDatabase(
// Set the path to the database.
join(await getDatabasesPath(), 'mydatabase.db'),
onUpgrade: (db, version ...) {
return db.execute(
"ALTER TABLE ... ADD COLUMN ...",
);
},
// Set the version to upgrade
version: 2,
);
Upvotes: 1