db: use cursor

This commit is contained in:
Thibault Deckers 2024-10-18 20:16:24 +02:00
parent 7982c536e4
commit 76c3244074
2 changed files with 82 additions and 37 deletions

View file

@ -115,7 +115,7 @@ abstract class LocalMediaDb {
Future<Set<VideoPlaybackRow>> loadAllVideoPlayback(); Future<Set<VideoPlaybackRow>> loadAllVideoPlayback();
Future<VideoPlaybackRow?> loadVideoPlayback(int? id); Future<VideoPlaybackRow?> loadVideoPlayback(int id);
Future<void> addVideoPlayback(Set<VideoPlaybackRow> rows); Future<void> addVideoPlayback(Set<VideoPlaybackRow> rows);

View file

@ -31,6 +31,7 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
static const trashTable = 'trash'; static const trashTable = 'trash';
static const videoPlaybackTable = 'videoPlayback'; static const videoPlaybackTable = 'videoPlayback';
static const _queryCursorBufferSize = 1000;
static int _lastId = 0; static int _lastId = 0;
@override @override
@ -180,6 +181,7 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
whereArgs.add(origin); whereArgs.add(origin);
} }
final entries = <AvesEntry>{};
if (directory != null) { if (directory != null) {
final separator = pContext.separator; final separator = pContext.separator;
if (!directory.endsWith(separator)) { if (!directory.endsWith(separator)) {
@ -188,21 +190,25 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
where = '${where != null ? '$where AND ' : ''}path LIKE ?'; where = '${where != null ? '$where AND ' : ''}path LIKE ?';
whereArgs.add('$directory%'); whereArgs.add('$directory%');
final rows = await _db.query(entryTable, where: where, whereArgs: whereArgs); final cursor = await _db.queryCursor(entryTable, where: where, whereArgs: whereArgs, bufferSize: _queryCursorBufferSize);
final dirLength = directory.length; final dirLength = directory.length;
return rows while (await cursor.moveNext()) {
.whereNot((row) { final row = cursor.current;
// skip entries in subfolders // skip entries in subfolders
final path = row['path'] as String?; final path = row['path'] as String?;
return path == null || path.substring(dirLength).contains(separator); if (path != null && !path.substring(dirLength).contains(separator)) {
}) entries.add(AvesEntry.fromMap(row));
.map(AvesEntry.fromMap) }
.toSet(); }
} else {
final cursor = await _db.queryCursor(entryTable, where: where, whereArgs: whereArgs, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
entries.add(AvesEntry.fromMap(cursor.current));
}
} }
final rows = await _db.query(entryTable, where: where, whereArgs: whereArgs); return entries;
return rows.map(AvesEntry.fromMap).toSet();
} }
@override @override
@ -278,8 +284,13 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Map<int?, int?>> loadDates() async { Future<Map<int?, int?>> loadDates() async {
final rows = await _db.query(dateTakenTable); final result = <int?, int?>{};
return Map.fromEntries(rows.map((map) => MapEntry(map['id'] as int, (map['dateMillis'] ?? 0) as int))); final cursor = await _db.queryCursor(dateTakenTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
final row = cursor.current;
result[row['id'] as int] = row['dateMillis'] as int? ?? 0;
}
return result;
} }
// catalog metadata // catalog metadata
@ -292,8 +303,12 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<CatalogMetadata>> loadCatalogMetadata() async { Future<Set<CatalogMetadata>> loadCatalogMetadata() async {
final rows = await _db.query(metadataTable); final result = <CatalogMetadata>{};
return rows.map(CatalogMetadata.fromMap).toSet(); final cursor = await _db.queryCursor(metadataTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
result.add(CatalogMetadata.fromMap(cursor.current));
}
return result;
} }
@override @override
@ -351,8 +366,12 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<AddressDetails>> loadAddresses() async { Future<Set<AddressDetails>> loadAddresses() async {
final rows = await _db.query(addressTable); final result = <AddressDetails>{};
return rows.map(AddressDetails.fromMap).toSet(); final cursor = await _db.queryCursor(addressTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
result.add(AddressDetails.fromMap(cursor.current));
}
return result;
} }
@override @override
@ -395,8 +414,12 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<VaultDetails>> loadAllVaults() async { Future<Set<VaultDetails>> loadAllVaults() async {
final rows = await _db.query(vaultTable); final result = <VaultDetails>{};
return rows.map(VaultDetails.fromMap).toSet(); final cursor = await _db.queryCursor(vaultTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
result.add(VaultDetails.fromMap(cursor.current));
}
return result;
} }
@override @override
@ -443,8 +466,12 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<TrashDetails>> loadAllTrashDetails() async { Future<Set<TrashDetails>> loadAllTrashDetails() async {
final rows = await _db.query(trashTable); final result = <TrashDetails>{};
return rows.map(TrashDetails.fromMap).toSet(); final cursor = await _db.queryCursor(trashTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
result.add(TrashDetails.fromMap(cursor.current));
}
return result;
} }
@override @override
@ -474,8 +501,12 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<FavouriteRow>> loadAllFavourites() async { Future<Set<FavouriteRow>> loadAllFavourites() async {
final rows = await _db.query(favouriteTable); final result = <FavouriteRow>{};
return rows.map(FavouriteRow.fromMap).toSet(); final cursor = await _db.queryCursor(favouriteTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
result.add(FavouriteRow.fromMap(cursor.current));
}
return result;
} }
@override @override
@ -524,8 +555,15 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<CoverRow>> loadAllCovers() async { Future<Set<CoverRow>> loadAllCovers() async {
final rows = await _db.query(coverTable); final result = <CoverRow>{};
return rows.map(CoverRow.fromMap).whereNotNull().toSet(); final cursor = await _db.queryCursor(coverTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
final row = CoverRow.fromMap(cursor.current);
if (row != null) {
result.add(row);
}
}
return result;
} }
@override @override
@ -587,14 +625,19 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
@override @override
Future<Set<VideoPlaybackRow>> loadAllVideoPlayback() async { Future<Set<VideoPlaybackRow>> loadAllVideoPlayback() async {
final rows = await _db.query(videoPlaybackTable); final result = <VideoPlaybackRow>{};
return rows.map(VideoPlaybackRow.fromMap).whereNotNull().toSet(); final cursor = await _db.queryCursor(videoPlaybackTable, bufferSize: _queryCursorBufferSize);
while (await cursor.moveNext()) {
final row = VideoPlaybackRow.fromMap(cursor.current);
if (row != null) {
result.add(row);
}
}
return result;
} }
@override @override
Future<VideoPlaybackRow?> loadVideoPlayback(int? id) async { Future<VideoPlaybackRow?> loadVideoPlayback(int id) async {
if (id == null) return null;
final rows = await _db.query(videoPlaybackTable, where: 'id = ?', whereArgs: [id]); final rows = await _db.query(videoPlaybackTable, where: 'id = ?', whereArgs: [id]);
if (rows.isEmpty) return null; if (rows.isEmpty) return null;
@ -631,11 +674,13 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
// convenience methods // convenience methods
Future<Set<T>> _getByIds<T>(Set<int> ids, String table, T Function(Map<String, Object?> row) mapRow) async { Future<Set<T>> _getByIds<T>(Set<int> ids, String table, T Function(Map<String, Object?> row) mapRow) async {
if (ids.isEmpty) return {}; final result = <T>{};
final rows = await _db.query( if (ids.isNotEmpty) {
table, final cursor = await _db.queryCursor(table, where: 'id IN (${ids.join(',')})', bufferSize: _queryCursorBufferSize);
where: 'id IN (${ids.join(',')})', while (await cursor.moveNext()) {
); result.add(mapRow(cursor.current));
return rows.map(mapRow).toSet(); }
}
return result;
} }
} }