mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
fix: sqlite parameters limit (#22119)
* fix isNotIns * fix isIns --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
33d76fb386
commit
e1e24f3d60
13 changed files with 109 additions and 47 deletions
BIN
mobile/drift_schemas/main/drift_schema_v11.json
generated
Normal file
BIN
mobile/drift_schemas/main/drift_schema_v11.json
generated
Normal file
Binary file not shown.
|
|
@ -10,6 +10,9 @@ class LocalAlbumAssetEntity extends Table with DriftDefaultsMixin {
|
||||||
|
|
||||||
TextColumn get albumId => text().references(LocalAlbumEntity, #id, onDelete: KeyAction.cascade)();
|
TextColumn get albumId => text().references(LocalAlbumEntity, #id, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
// Used for mark & sweep
|
||||||
|
BoolColumn get marker_ => boolean().nullable()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {assetId, albumId};
|
Set<Column> get primaryKey => {assetId, albumId};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -93,7 +93,7 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 10;
|
int get schemaVersion => 11;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
|
|
@ -156,6 +156,9 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||||
await m.addColumn(v10.userEntity, v10.userEntity.avatarColor);
|
await m.addColumn(v10.userEntity, v10.userEntity.avatarColor);
|
||||||
await m.alterTable(TableMigration(v10.userEntity));
|
await m.alterTable(TableMigration(v10.userEntity));
|
||||||
},
|
},
|
||||||
|
from10To11: (m, v11) async {
|
||||||
|
await m.addColumn(v11.localAlbumAssetEntity, v11.localAlbumAssetEntity.marker_);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -72,17 +72,33 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
final deleteSmt = _db.localAssetEntity.delete();
|
return _db.transaction(() async {
|
||||||
deleteSmt.where((localAsset) {
|
await _db.managers.localAlbumAssetEntity
|
||||||
final subQuery = _db.localAlbumAssetEntity.selectOnly()
|
.filter((row) => row.albumId.id.equals(albumId))
|
||||||
..addColumns([_db.localAlbumAssetEntity.assetId])
|
.update((album) => album(marker_: const Value(true)));
|
||||||
..join([innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id))]);
|
|
||||||
subQuery.where(
|
await _db.batch((batch) {
|
||||||
_db.localAlbumEntity.id.equals(albumId) & _db.localAlbumAssetEntity.assetId.isNotIn(assetIdsToKeep),
|
for (final assetId in assetIdsToKeep) {
|
||||||
);
|
batch.update(
|
||||||
return localAsset.id.isInQuery(subQuery);
|
_db.localAlbumAssetEntity,
|
||||||
|
const LocalAlbumAssetEntityCompanion(marker_: Value(null)),
|
||||||
|
where: (row) => row.assetId.equals(assetId) & row.albumId.equals(albumId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final query = _db.localAssetEntity.delete()
|
||||||
|
..where(
|
||||||
|
(row) => row.id.isInQuery(
|
||||||
|
_db.localAlbumAssetEntity.selectOnly()
|
||||||
|
..addColumns([_db.localAlbumAssetEntity.assetId])
|
||||||
|
..where(
|
||||||
|
_db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAlbumAssetEntity.marker_.isNotNull(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await query.go();
|
||||||
});
|
});
|
||||||
await deleteSmt.go();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> upsert(
|
Future<void> upsert(
|
||||||
|
|
@ -198,10 +214,9 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
// List<String>
|
// List<String>
|
||||||
await _db.batch((batch) async {
|
await _db.batch((batch) async {
|
||||||
assetAlbums.cast<String, List<Object?>>().forEach((assetId, albumIds) {
|
assetAlbums.cast<String, List<Object?>>().forEach((assetId, albumIds) {
|
||||||
batch.deleteWhere(
|
for (final albumId in albumIds.cast<String?>().nonNulls) {
|
||||||
_db.localAlbumAssetEntity,
|
batch.deleteWhere(_db.localAlbumAssetEntity, (f) => f.albumId.equals(albumId) & f.assetId.equals(assetId));
|
||||||
(f) => f.albumId.isNotIn(albumIds.cast<String?>().nonNulls) & f.assetId.equals(assetId),
|
}
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await _db.batch((batch) async {
|
await _db.batch((batch) async {
|
||||||
|
|
@ -288,12 +303,14 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
if (assetsToUnLink.isNotEmpty) {
|
if (assetsToUnLink.isNotEmpty) {
|
||||||
await _db.batch(
|
await _db.batch((batch) {
|
||||||
(batch) => batch.deleteWhere(
|
for (final assetId in assetsToUnLink) {
|
||||||
_db.localAlbumAssetEntity,
|
batch.deleteWhere(
|
||||||
(f) => f.assetId.isIn(assetsToUnLink) & f.albumId.equals(albumId),
|
_db.localAlbumAssetEntity,
|
||||||
),
|
(row) => row.assetId.equals(assetId) & row.albumId.equals(albumId),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await _deleteAssets(assetsToDelete);
|
await _deleteAssets(assetsToDelete);
|
||||||
|
|
@ -320,7 +337,9 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
return _db.batch((batch) {
|
return _db.batch((batch) {
|
||||||
batch.deleteWhere(_db.localAssetEntity, (f) => f.id.isIn(ids));
|
for (final id in ids) {
|
||||||
|
batch.deleteWhere(_db.localAssetEntity, (row) => row.id.equals(id));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
|
@ -58,8 +57,8 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
return _db.batch((batch) {
|
return _db.batch((batch) {
|
||||||
for (final slice in ids.slices(32000)) {
|
for (final id in ids) {
|
||||||
batch.deleteWhere(_db.localAssetEntity, (e) => e.id.isIn(slice));
|
batch.deleteWhere(_db.localAssetEntity, (e) => e.id.equals(id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,8 +166,15 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> removeAssets(String albumId, List<String> assetIds) {
|
Future<void> removeAssets(String albumId, List<String> assetIds) {
|
||||||
return _db.remoteAlbumAssetEntity.deleteWhere((tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds));
|
return _db.batch((batch) {
|
||||||
|
for (final assetId in assetIds) {
|
||||||
|
batch.deleteWhere(
|
||||||
|
_db.remoteAlbumAssetEntity,
|
||||||
|
(row) => row.albumId.equals(albumId) & row.assetId.equals(assetId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureOr<(DateTime, DateTime)> getDateRange(String albumId) {
|
FutureOr<(DateTime, DateTime)> getDateRange(String albumId) {
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> delete(List<String> ids) {
|
Future<void> delete(List<String> ids) {
|
||||||
return _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(ids));
|
return _db.batch((batch) {
|
||||||
|
for (final id in ids) {
|
||||||
|
batch.deleteWhere(_db.remoteAssetEntity, (row) => row.id.equals(id));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateLocation(List<String> ids, LatLng location) {
|
Future<void> updateLocation(List<String> ids, LatLng location) {
|
||||||
|
|
@ -199,7 +203,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
.map((row) => row.id)
|
.map((row) => row.id)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds));
|
await _db.batch((batch) {
|
||||||
|
for (final stackId in stackIds) {
|
||||||
|
batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stackId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
final companion = StackEntityCompanion(ownerId: Value(userId), primaryAssetId: Value(stack.primaryAssetId));
|
final companion = StackEntityCompanion(ownerId: Value(userId), primaryAssetId: Value(stack.primaryAssetId));
|
||||||
|
|
@ -219,15 +227,21 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> unStack(List<String> stackIds) {
|
Future<void> unStack(List<String> stackIds) {
|
||||||
return _db.transaction(() async {
|
return _db.transaction(() async {
|
||||||
await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds));
|
await _db.batch((batch) {
|
||||||
|
for (final stackId in stackIds) {
|
||||||
|
batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stackId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: delete this after adding foreign key on stackId
|
// TODO: delete this after adding foreign key on stackId
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
batch.update(
|
for (final stackId in stackIds) {
|
||||||
_db.remoteAssetEntity,
|
batch.update(
|
||||||
const RemoteAssetEntityCompanion(stackId: Value(null)),
|
_db.remoteAssetEntity,
|
||||||
where: (e) => e.stackId.isIn(stackIds),
|
const RemoteAssetEntityCompanion(stackId: Value(null)),
|
||||||
);
|
where: (e) => e.stackId.equals(stackId),
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.userEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.userId)));
|
await _db.batch((batch) {
|
||||||
|
for (final user in data) {
|
||||||
|
batch.deleteWhere(_db.userEntity, (row) => row.id.equals(user.userId));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: SyncUserDeleteV1', error, stack);
|
_logger.severe('Error: SyncUserDeleteV1', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -158,7 +162,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data, {String debugLabel = 'user'}) async {
|
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data, {String debugLabel = 'user'}) async {
|
||||||
try {
|
try {
|
||||||
await _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId)));
|
await _db.batch((batch) {
|
||||||
|
for (final asset in data) {
|
||||||
|
batch.deleteWhere(_db.remoteAssetEntity, (row) => row.id.equals(asset.assetId));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack);
|
_logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -243,7 +251,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteAlbumsV1(Iterable<SyncAlbumDeleteV1> data) async {
|
Future<void> deleteAlbumsV1(Iterable<SyncAlbumDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.remoteAlbumEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId)));
|
await _db.batch((batch) {
|
||||||
|
for (final album in data) {
|
||||||
|
batch.deleteWhere(_db.remoteAlbumEntity, (row) => row.id.equals(album.albumId));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteAlbumsV1', error, stack);
|
_logger.severe('Error: deleteAlbumsV1', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -379,7 +391,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteMemoriesV1(Iterable<SyncMemoryDeleteV1> data) async {
|
Future<void> deleteMemoriesV1(Iterable<SyncMemoryDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.memoryEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.memoryId)));
|
await _db.batch((batch) {
|
||||||
|
for (final memory in data) {
|
||||||
|
batch.deleteWhere(_db.memoryEntity, (row) => row.id.equals(memory.memoryId));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteMemoriesV1', error, stack);
|
_logger.severe('Error: deleteMemoriesV1', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
@ -443,7 +459,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
Future<void> deleteStacksV1(Iterable<SyncStackDeleteV1> data, {String debugLabel = 'user'}) async {
|
Future<void> deleteStacksV1(Iterable<SyncStackDeleteV1> data, {String debugLabel = 'user'}) async {
|
||||||
try {
|
try {
|
||||||
await _db.stackEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.stackId)));
|
await _db.batch((batch) {
|
||||||
|
for (final stack in data) {
|
||||||
|
batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stack.stackId));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack);
|
_logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:immich_mobile/repositories/download.repository.dart';
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
|
|
@ -11,6 +10,7 @@ import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||||
|
import 'package:immich_mobile/repositories/download.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/widgets/common/date_time_picker.dart';
|
import 'package:immich_mobile/widgets/common/date_time_picker.dart';
|
||||||
|
|
@ -199,14 +199,11 @@ class ActionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> removeFromAlbum(List<String> remoteIds, String albumId) async {
|
Future<int> removeFromAlbum(List<String> remoteIds, String albumId) async {
|
||||||
int removedCount = 0;
|
|
||||||
final result = await _albumApiRepository.removeAssets(albumId, remoteIds);
|
final result = await _albumApiRepository.removeAssets(albumId, remoteIds);
|
||||||
|
|
||||||
if (result.removed.isNotEmpty) {
|
if (result.removed.isNotEmpty) {
|
||||||
removedCount = await _remoteAlbumRepository.removeAssets(albumId, result.removed);
|
await _remoteAlbumRepository.removeAssets(albumId, result.removed);
|
||||||
}
|
}
|
||||||
|
return result.removed.length;
|
||||||
return removedCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> updateDescription(String assetId, String description) async {
|
Future<bool> updateDescription(String assetId, String description) async {
|
||||||
|
|
|
||||||
BIN
mobile/test/drift/main/generated/schema.dart
generated
BIN
mobile/test/drift/main/generated/schema.dart
generated
Binary file not shown.
BIN
mobile/test/drift/main/generated/schema_v11.dart
generated
Normal file
BIN
mobile/test/drift/main/generated/schema_v11.dart
generated
Normal file
Binary file not shown.
Loading…
Reference in a new issue