[mob][photos] Migrate to sqlite_async(10)

This commit is contained in:
ashilkn 2024-05-16 18:02:39 +05:30
parent dec7c45310
commit 16d54645bc

View file

@ -22,61 +22,55 @@ extension DeviceFiles on FilesDB {
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.ignore,
}) async {
debugPrint("Inserting missing PathIDToLocalIDMapping");
final db = await database;
var batch = db.batch();
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (MapEntry e in mappingToAdd.entries) {
final String pathID = e.key;
for (String localID in e.value) {
parameterSets.add([localID, pathID]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await _insertBatch(parameterSets, conflictAlgorithm);
parameterSets.clear();
batchCounter = 0;
}
batch.insert(
"device_files",
{
"id": localID,
"path_id": pathID,
},
conflictAlgorithm: conflictAlgorithm,
);
batchCounter++;
}
}
await batch.commit(noResult: true);
await _insertBatch(parameterSets, conflictAlgorithm);
parameterSets.clear();
batchCounter = 0;
}
Future<void> deletePathIDToLocalIDMapping(
Map<String, Set<String>> mappingsToRemove,
) async {
debugPrint("removing PathIDToLocalIDMapping");
final db = await database;
var batch = db.batch();
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (MapEntry e in mappingsToRemove.entries) {
final String pathID = e.key;
for (String localID in e.value) {
parameterSets.add([localID, pathID]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await _deleteBatch(parameterSets);
parameterSets.clear();
batchCounter = 0;
}
batch.delete(
"device_files",
where: 'id = ? AND path_id = ?',
whereArgs: [localID, pathID],
);
batchCounter++;
}
}
await batch.commit(noResult: true);
await _deleteBatch(parameterSets);
parameterSets.clear();
batchCounter = 0;
}
Future<Map<String, int>> getDevicePathIDToImportedFileCount() async {
try {
final db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT count(*) as count, path_id
FROM device_files
@ -96,8 +90,8 @@ extension DeviceFiles on FilesDB {
Future<Map<String, Set<String>>> getDevicePathIDToLocalIDMap() async {
try {
final db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
''' SELECT id, path_id FROM device_files; ''',
);
final result = <String, Set<String>>{};
@ -116,8 +110,8 @@ extension DeviceFiles on FilesDB {
}
Future<Set<String>> getDevicePathIDs() async {
final Database db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT id FROM device_collections
''',
@ -133,34 +127,42 @@ extension DeviceFiles on FilesDB {
List<LocalPathAsset> localPathAssets, {
bool shouldAutoBackup = false,
}) async {
final Database db = await database;
final db = await sqliteAsyncDB;
final Map<String, Set<String>> pathIDToLocalIDsMap = {};
try {
final batch = db.batch();
final Set<String> existingPathIds = await getDevicePathIDs();
final parameterSetsForUpdate = <List<Object?>>[];
final parameterSetsForInsert = <List<Object?>>[];
for (LocalPathAsset localPathAsset in localPathAssets) {
if (localPathAsset.localIDs.isNotEmpty) {
pathIDToLocalIDsMap[localPathAsset.pathID] = localPathAsset.localIDs;
}
if (existingPathIds.contains(localPathAsset.pathID)) {
batch.rawUpdate(
"UPDATE device_collections SET name = ? where id = "
"?",
[localPathAsset.pathName, localPathAsset.pathID],
);
parameterSetsForUpdate
.add([localPathAsset.pathName, localPathAsset.pathID]);
} else if (localPathAsset.localIDs.isNotEmpty) {
batch.insert(
"device_collections",
{
"id": localPathAsset.pathID,
"name": localPathAsset.pathName,
"should_backup": shouldAutoBackup ? _sqlBoolTrue : _sqlBoolFalse,
},
conflictAlgorithm: ConflictAlgorithm.ignore,
);
parameterSetsForInsert.add([
localPathAsset.pathID,
localPathAsset.pathName,
shouldAutoBackup ? _sqlBoolTrue : _sqlBoolFalse,
]);
}
}
await batch.commit(noResult: true);
await db.executeBatch(
'''
INSERT OR IGNORE INTO device_collections (id, name, should_backup) VALUES (?, ?, ?);
''',
parameterSetsForInsert,
);
await db.executeBatch(
'''
UPDATE device_collections SET name = ? WHERE id = ?;
''',
parameterSetsForUpdate,
);
// add the mappings for localIDs
if (pathIDToLocalIDsMap.isNotEmpty) {
await insertPathIDToLocalIDMapping(pathIDToLocalIDsMap);
@ -177,7 +179,7 @@ extension DeviceFiles on FilesDB {
}) async {
bool hasUpdated = false;
try {
final Database db = await database;
final db = await sqliteAsyncDB;
final Set<String> existingPathIds = await getDevicePathIDs();
for (Tuple2<AssetPathEntity, String> tup in devicePathInfo) {
final AssetPathEntity pathEntity = tup.item1;
@ -185,35 +187,42 @@ extension DeviceFiles on FilesDB {
final String localID = tup.item2;
final bool shouldUpdate = existingPathIds.contains(pathEntity.id);
if (shouldUpdate) {
final rowUpdated = await db.rawUpdate(
"UPDATE device_collections SET name = ?, cover_id = ?, count"
" = ? where id = ? AND (name != ? OR cover_id != ? OR count != ?)",
[
pathEntity.name,
localID,
assetCount,
pathEntity.id,
pathEntity.name,
localID,
assetCount,
],
);
final rowUpdated = await db.writeTransaction((tx) async {
await tx.execute(
"UPDATE device_collections SET name = ?, cover_id = ?, count"
" = ? where id = ? AND (name != ? OR cover_id != ? OR count != ?)",
[
pathEntity.name,
localID,
assetCount,
pathEntity.id,
pathEntity.name,
localID,
assetCount,
],
);
final result = await tx.get("SELECT changes();");
return result["changes()"] as int;
});
if (rowUpdated > 0) {
_logger.fine("Updated $rowUpdated rows for ${pathEntity.name}");
hasUpdated = true;
}
} else {
hasUpdated = true;
await db.insert(
"device_collections",
{
"id": pathEntity.id,
"name": pathEntity.name,
"count": assetCount,
"cover_id": localID,
"should_backup": shouldBackup ? _sqlBoolTrue : _sqlBoolFalse,
},
conflictAlgorithm: ConflictAlgorithm.ignore,
await db.execute(
'''
INSERT INTO device_collections (id, name, count, cover_id, should_backup)
VALUES (?, ?, ?, ?, ?);
''',
[
pathEntity.id,
pathEntity.name,
assetCount,
localID,
shouldBackup ? _sqlBoolTrue : _sqlBoolFalse,
],
);
}
}
@ -231,15 +240,17 @@ extension DeviceFiles on FilesDB {
// feature, where we delete files which are backed up. Deleting such
// entries here result in us losing out on the information that
// those folders were marked for automatic backup.
await db.delete(
"device_collections",
where: 'id = ? and should_backup = $_sqlBoolFalse ',
whereArgs: [pathID],
await db.execute(
'''
DELETE FROM device_collections WHERE id = ? AND should_backup = $_sqlBoolFalse;
''',
[pathID],
);
await db.delete(
"device_files",
where: 'path_id = ?',
whereArgs: [pathID],
await db.execute(
'''
DELETE FROM device_files WHERE path_id = ?;
''',
[pathID],
);
}
}
@ -253,8 +264,8 @@ extension DeviceFiles on FilesDB {
// getDeviceSyncCollectionIDs returns the collectionIDs for the
// deviceCollections which are marked for auto-backup
Future<Set<int>> getDeviceSyncCollectionIDs() async {
final Database db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT collection_id FROM device_collections where should_backup =
$_sqlBoolTrue
@ -447,4 +458,28 @@ extension DeviceFiles on FilesDB {
return null;
}
}
Future<void> _insertBatch(
List<List<Object?>> parameterSets,
ConflictAlgorithm conflictAlgorithm,
) async {
final db = await sqliteAsyncDB;
await db.executeBatch(
'''
INSERT OR ${conflictAlgorithm.name.toUpperCase()}
INTO device_files (id, path_id) VALUES (?, ?);
''',
parameterSets,
);
}
Future<void> _deleteBatch(List<List<Object?>> parameterSets) async {
final db = await sqliteAsyncDB;
await db.executeBatch(
'''
DELETE FROM device_files WHERE id = ? AND path_id = ?;
''',
parameterSets,
);
}
}