file_migration_db.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import 'dart:io';
  2. import 'package:logging/logging.dart';
  3. import 'package:path/path.dart';
  4. import 'package:path_provider/path_provider.dart';
  5. import 'package:sqflite/sqflite.dart';
  6. class FilesMigrationDB {
  7. static const _databaseName = "ente.files_migration.db";
  8. static const _databaseVersion = 1;
  9. static final Logger _logger = Logger((FilesMigrationDB).toString());
  10. static const tableName = 're_upload_tracker';
  11. static const columnLocalID = 'local_id';
  12. Future _onCreate(Database db, int version) async {
  13. await db.execute(
  14. '''
  15. CREATE TABLE $tableName (
  16. $columnLocalID TEXT NOT NULL,
  17. UNIQUE($columnLocalID)
  18. );
  19. ''',
  20. );
  21. }
  22. FilesMigrationDB._privateConstructor();
  23. static final FilesMigrationDB instance =
  24. FilesMigrationDB._privateConstructor();
  25. // only have a single app-wide reference to the database
  26. static Future<Database> _dbFuture;
  27. Future<Database> get database async {
  28. // lazily instantiate the db the first time it is accessed
  29. _dbFuture ??= _initDatabase();
  30. return _dbFuture;
  31. }
  32. // this opens the database (and creates it if it doesn't exist)
  33. Future<Database> _initDatabase() async {
  34. final Directory documentsDirectory = await getApplicationDocumentsDirectory();
  35. final String path = join(documentsDirectory.path, _databaseName);
  36. return await openDatabase(
  37. path,
  38. version: _databaseVersion,
  39. onCreate: _onCreate,
  40. );
  41. }
  42. Future<void> clearTable() async {
  43. final db = await instance.database;
  44. await db.delete(tableName);
  45. }
  46. Future<void> insertMultiple(List<String> fileLocalIDs) async {
  47. final startTime = DateTime.now();
  48. final db = await instance.database;
  49. var batch = db.batch();
  50. int batchCounter = 0;
  51. for (String localID in fileLocalIDs) {
  52. if (batchCounter == 400) {
  53. await batch.commit(noResult: true);
  54. batch = db.batch();
  55. batchCounter = 0;
  56. }
  57. batch.insert(
  58. tableName,
  59. _getRowForReUploadTable(localID),
  60. conflictAlgorithm: ConflictAlgorithm.replace,
  61. );
  62. batchCounter++;
  63. }
  64. await batch.commit(noResult: true);
  65. final endTime = DateTime.now();
  66. final duration = Duration(
  67. microseconds:
  68. endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
  69. );
  70. _logger.info(
  71. "Batch insert of ${fileLocalIDs.length} "
  72. "took ${duration.inMilliseconds} ms.",
  73. );
  74. }
  75. Future<int> deleteByLocalIDs(List<String> localIDs) async {
  76. String inParam = "";
  77. for (final localID in localIDs) {
  78. inParam += "'" + localID + "',";
  79. }
  80. inParam = inParam.substring(0, inParam.length - 1);
  81. final db = await instance.database;
  82. return await db.delete(
  83. tableName,
  84. where: '$columnLocalID IN (${localIDs.join(', ')})',
  85. );
  86. }
  87. Future<List<String>> getLocalIDsForPotentialReUpload(int limit) async {
  88. final db = await instance.database;
  89. final rows = await db.query(tableName, limit: limit);
  90. final result = <String>[];
  91. for (final row in rows) {
  92. result.add(row[columnLocalID]);
  93. }
  94. return result;
  95. }
  96. Map<String, dynamic> _getRowForReUploadTable(String localID) {
  97. assert(localID != null);
  98. final row = <String, dynamic>{};
  99. row[columnLocalID] = localID;
  100. return row;
  101. }
  102. }