[mob][photos] Migrate to sqlite_async)(6): Migrate insertMultipleNew to use sqlite_async

This commit is contained in:
ashilkn 2024-05-15 19:52:55 +05:30
parent d1a5921c27
commit 25554209ec
2 changed files with 163 additions and 1 deletions

View file

@ -15,6 +15,7 @@ import 'package:photos/models/location/location.dart';
import "package:photos/models/metadata/common_keys.dart";
import "package:photos/services/filter/db_filters.dart";
import 'package:photos/utils/file_uploader_util.dart';
import "package:photos/utils/primitive_wrapper.dart";
import 'package:sqflite/sqflite.dart';
import 'package:sqflite_migration/sqflite_migration.dart';
import 'package:sqlite_async/sqlite_async.dart' as sqlite_async;
@ -91,6 +92,39 @@ class FilesDB {
...addAddedTime(),
];
static const List<String> _columnNames = [
columnGeneratedID,
columnLocalID,
columnUploadedFileID,
columnOwnerID,
columnCollectionID,
columnTitle,
columnDeviceFolder,
columnLatitude,
columnLongitude,
columnFileType,
columnModificationTime,
columnEncryptedKey,
columnKeyDecryptionNonce,
columnFileDecryptionHeader,
columnThumbnailDecryptionHeader,
columnMetadataDecryptionHeader,
columnCreationTime,
columnUpdationTime,
columnFileSubType,
columnDuration,
columnExif,
columnHash,
columnMetadataVersion,
columnMMdEncodedJson,
columnMMdVersion,
columnMMdVisibility,
columnPubMMdEncodedJson,
columnPubMMdVersion,
columnFileSize,
columnAddedTime,
];
final dbConfig = MigrationConfig(
initializationScript: initializationScript,
migrationScripts: migrationScripts,
@ -455,6 +489,128 @@ class FilesDB {
);
}
Future<void> insertMultipleNew(
List<EnteFile> files, {
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
}) async {
final startTime = DateTime.now();
final db = await sqliteAsyncDB;
///Strong batch counter in an object so that it gets passed by reference
///Primitives are passed by value
final genIdNotNullbatchCounter = PrimitiveWrapper(0);
final genIdNullbatchCounter = PrimitiveWrapper(0);
final genIdNullParameterSets = <List<Object?>>[];
final genIdNotNullParameterSets = <List<Object?>>[];
final genIdNullcolumnNames =
_columnNames.where((element) => element != columnGeneratedID);
for (EnteFile file in files) {
final fileGenIdIsNull = file.generatedID == null;
if (!fileGenIdIsNull) {
await _batchAndInsertFile(
file,
conflictAlgorithm,
db,
genIdNotNullParameterSets,
genIdNotNullbatchCounter,
isGenIdNull: fileGenIdIsNull,
);
} else {
await _batchAndInsertFile(
file,
conflictAlgorithm,
db,
genIdNullParameterSets,
genIdNullbatchCounter,
isGenIdNull: fileGenIdIsNull,
);
}
}
if (genIdNotNullbatchCounter.value > 0) {
await _insertBatch(
conflictAlgorithm,
_columnNames,
db,
genIdNotNullParameterSets,
);
genIdNotNullbatchCounter.value = 0;
genIdNotNullParameterSets.clear();
}
if (genIdNullbatchCounter.value > 0) {
await _insertBatch(
conflictAlgorithm,
genIdNullcolumnNames,
db,
genIdNullParameterSets,
);
genIdNullbatchCounter.value = 0;
genIdNullParameterSets.clear();
}
final endTime = DateTime.now();
final duration = Duration(
microseconds:
endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch,
);
_logger.info(
"Batch insert of " +
files.length.toString() +
" took " +
duration.inMilliseconds.toString() +
"ms.",
);
}
@pragma('vm:prefer-inline')
Future<void> _batchAndInsertFile(
EnteFile file,
ConflictAlgorithm conflictAlgorithm,
sqlite_async.SqliteDatabase db,
List<List<Object?>> parameterSets,
PrimitiveWrapper batchCounter, {
required bool isGenIdNull,
}) async {
parameterSets.add(_getParameterSetForFileV2(file));
batchCounter.value++;
final columnNames = isGenIdNull
? _columnNames.where((column) => column != columnGeneratedID)
: _columnNames;
if (batchCounter.value == 400) {
_logger.info("Inserting batch with genIdNull: $isGenIdNull");
await _insertBatch(conflictAlgorithm, columnNames, db, parameterSets);
// await db.executeBatch(
// '''
// INSERT OR ${conflictAlgorithm.name.toUpperCase()} INTO $filesTable($columnNames) VALUES($valuesPlaceholders)
// ''',
// parameterSets,
// );
batchCounter.value = 0;
parameterSets.clear();
}
}
Future<void> _insertBatch(
ConflictAlgorithm conflictAlgorithm,
Iterable<String> columnNames,
sqlite_async.SqliteDatabase db,
List<List<Object?>> parameterSets,
) async {
final valuesPlaceholders = List.filled(columnNames.length, "?").join(",");
final columnNamesJoined = columnNames.join(",");
await db.executeBatch(
'''
INSERT OR ${conflictAlgorithm.name.toUpperCase()} INTO $filesTable($columnNamesJoined) VALUES($valuesPlaceholders)
''',
parameterSets,
);
}
@pragma('vm:prefer-inline')
Future<int> insert(EnteFile file) async {
_logger.info("Inserting $file");
final db = await instance.database;
@ -1687,7 +1843,7 @@ class FilesDB {
return values;
}
List<Object?> _getParameterSetForFileNew(
List<Object?> _getParameterSetForFileV2(
EnteFile file, {
bool omitNullGenId = true,
}) {

View file

@ -0,0 +1,6 @@
///This is useful when you want to pass a primitive by reference.
class PrimitiveWrapper {
var value;
PrimitiveWrapper(this.value);
}