use a separate table instead of a column on remote asset

This commit is contained in:
shenlong-tanwen
2025-09-06 01:50:48 +05:30
parent 5236a72fb3
commit 03cd491197
16 changed files with 853 additions and 216 deletions
@@ -17,6 +17,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset_cloud_id.entity.dart';
import 'package:immich_mobile/infrastructure/entities/stack.entity.dart';
import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
@@ -54,6 +55,7 @@ class IsarDatabaseRepository implements IDatabaseRepository {
RemoteAlbumEntity,
RemoteAlbumAssetEntity,
RemoteAlbumUserEntity,
RemoteAssetCloudIdEntity,
MemoryEntity,
MemoryAssetEntity,
StackEntity,
@@ -123,14 +125,6 @@ class Drift extends $Drift implements IDatabaseRepository {
from7To8: (m, v8) async {
await m.create(v8.storeEntity);
},
from8To9: (m, v9) async {
// Add cloudId column to local_asset_entity
await m.addColumn(v9.localAssetEntity, v9.localAssetEntity.cloudId);
await m.createIndex(v9.idxLocalAssetCloudId);
// Add cloudId column to remote_asset_entity
await m.addColumn(v9.remoteAssetEntity, v9.remoteAssetEntity.cloudId);
await m.createIndex(v9.idxRemoteAssetCloudId);
},
from8To9: (m, v9) async {
await m.addColumn(v9.localAlbumEntity, v9.localAlbumEntity.linkedRemoteAlbumId);
},
@@ -138,8 +132,7 @@ class Drift extends $Drift implements IDatabaseRepository {
// Add cloud_id to local and remote asset tables
await m.addColumn(v10.localAssetEntity, v10.localAssetEntity.cloudId);
await m.createIndex(v10.idxLocalAssetCloudId);
await m.addColumn(v10.remoteAssetEntity, v10.remoteAssetEntity.cloudId);
await m.createIndex(v10.idxRemoteAssetCloudId);
await m.createTable(v10.remoteAssetCloudIdEntity);
},
),
);
@@ -25,19 +25,21 @@ import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.
as i11;
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart'
as i12;
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/remote_asset_cloud_id.entity.drift.dart'
as i13;
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'
as i14;
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'
as i15;
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'
as i16;
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'
as i17;
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
as i18;
import 'package:drift/internal/modular.dart' as i19;
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
as i19;
import 'package:drift/internal/modular.dart' as i20;
abstract class $Drift extends i0.GeneratedDatabase {
$Drift(i0.QueryExecutor e) : super(e);
@@ -65,16 +67,18 @@ abstract class $Drift extends i0.GeneratedDatabase {
.$RemoteAlbumAssetEntityTable(this);
late final i12.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i12
.$RemoteAlbumUserEntityTable(this);
late final i13.$MemoryEntityTable memoryEntity = i13.$MemoryEntityTable(this);
late final i14.$MemoryAssetEntityTable memoryAssetEntity = i14
late final i13.$RemoteAssetCloudIdEntityTable remoteAssetCloudIdEntity = i13
.$RemoteAssetCloudIdEntityTable(this);
late final i14.$MemoryEntityTable memoryEntity = i14.$MemoryEntityTable(this);
late final i15.$MemoryAssetEntityTable memoryAssetEntity = i15
.$MemoryAssetEntityTable(this);
late final i15.$PersonEntityTable personEntity = i15.$PersonEntityTable(this);
late final i16.$AssetFaceEntityTable assetFaceEntity = i16
late final i16.$PersonEntityTable personEntity = i16.$PersonEntityTable(this);
late final i17.$AssetFaceEntityTable assetFaceEntity = i17
.$AssetFaceEntityTable(this);
late final i17.$StoreEntityTable storeEntity = i17.$StoreEntityTable(this);
i18.MergedAssetDrift get mergedAssetDrift => i19.ReadDatabaseContainer(
late final i18.$StoreEntityTable storeEntity = i18.$StoreEntityTable(this);
i19.MergedAssetDrift get mergedAssetDrift => i20.ReadDatabaseContainer(
this,
).accessor<i18.MergedAssetDrift>(i18.MergedAssetDrift.new);
).accessor<i19.MergedAssetDrift>(i19.MergedAssetDrift.new);
@override
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
@@ -93,12 +97,12 @@ abstract class $Drift extends i0.GeneratedDatabase {
i2.uQRemoteAssetsOwnerChecksum,
i2.uQRemoteAssetsOwnerLibraryChecksum,
i2.idxRemoteAssetChecksum,
i2.idxRemoteAssetCloudId,
userMetadataEntity,
partnerEntity,
remoteExifEntity,
remoteAlbumAssetEntity,
remoteAlbumUserEntity,
remoteAssetCloudIdEntity,
memoryEntity,
memoryAssetEntity,
personEntity,
@@ -238,6 +242,18 @@ abstract class $Drift extends i0.GeneratedDatabase {
i0.TableUpdate('remote_album_user_entity', kind: i0.UpdateKind.delete),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName(
'remote_asset_entity',
limitUpdateKind: i0.UpdateKind.delete,
),
result: [
i0.TableUpdate(
'remote_asset_cloud_id_entity',
kind: i0.UpdateKind.delete,
),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName(
'user_entity',
@@ -320,14 +336,20 @@ class $DriftManager {
);
i12.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i12
.$$RemoteAlbumUserEntityTableTableManager(_db, _db.remoteAlbumUserEntity);
i13.$$MemoryEntityTableTableManager get memoryEntity =>
i13.$$MemoryEntityTableTableManager(_db, _db.memoryEntity);
i14.$$MemoryAssetEntityTableTableManager get memoryAssetEntity =>
i14.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity);
i15.$$PersonEntityTableTableManager get personEntity =>
i15.$$PersonEntityTableTableManager(_db, _db.personEntity);
i16.$$AssetFaceEntityTableTableManager get assetFaceEntity =>
i16.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
i17.$$StoreEntityTableTableManager get storeEntity =>
i17.$$StoreEntityTableTableManager(_db, _db.storeEntity);
i13.$$RemoteAssetCloudIdEntityTableTableManager
get remoteAssetCloudIdEntity =>
i13.$$RemoteAssetCloudIdEntityTableTableManager(
_db,
_db.remoteAssetCloudIdEntity,
);
i14.$$MemoryEntityTableTableManager get memoryEntity =>
i14.$$MemoryEntityTableTableManager(_db, _db.memoryEntity);
i15.$$MemoryAssetEntityTableTableManager get memoryAssetEntity =>
i15.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity);
i16.$$PersonEntityTableTableManager get personEntity =>
i16.$$PersonEntityTableTableManager(_db, _db.personEntity);
i17.$$AssetFaceEntityTableTableManager get assetFaceEntity =>
i17.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
i18.$$StoreEntityTableTableManager get storeEntity =>
i18.$$StoreEntityTableTableManager(_db, _db.storeEntity);
}
@@ -3838,12 +3838,12 @@ final class Schema10 extends i0.VersionedSchema {
uQRemoteAssetsOwnerChecksum,
uQRemoteAssetsOwnerLibraryChecksum,
idxRemoteAssetChecksum,
idxRemoteAssetCloudId,
userMetadataEntity,
partnerEntity,
remoteExifEntity,
remoteAlbumAssetEntity,
remoteAlbumUserEntity,
remoteAssetCloudIdEntity,
memoryEntity,
memoryAssetEntity,
personEntity,
@@ -3870,7 +3870,7 @@ final class Schema10 extends i0.VersionedSchema {
),
alias: null,
);
late final Shape20 remoteAssetEntity = Shape20(
late final Shape17 remoteAssetEntity = Shape17(
source: i0.VersionedTable(
entityName: 'remote_asset_entity',
withoutRowId: true,
@@ -3895,7 +3895,6 @@ final class Schema10 extends i0.VersionedSchema {
_column_20,
_column_21,
_column_86,
_column_91,
],
attachedDatabase: database,
),
@@ -3912,7 +3911,7 @@ final class Schema10 extends i0.VersionedSchema {
),
alias: null,
);
late final Shape21 localAssetEntity = Shape21(
late final Shape20 localAssetEntity = Shape20(
source: i0.VersionedTable(
entityName: 'local_asset_entity',
withoutRowId: true,
@@ -4011,10 +4010,6 @@ final class Schema10 extends i0.VersionedSchema {
'idx_remote_asset_checksum',
'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)',
);
final i1.Index idxRemoteAssetCloudId = i1.Index(
'idx_remote_asset_cloud_id',
'CREATE INDEX IF NOT EXISTS idx_remote_asset_cloud_id ON remote_asset_entity (cloud_id)',
);
late final Shape4 userMetadataEntity = Shape4(
source: i0.VersionedTable(
entityName: 'user_metadata_entity',
@@ -4093,6 +4088,17 @@ final class Schema10 extends i0.VersionedSchema {
),
alias: null,
);
late final Shape21 remoteAssetCloudIdEntity = Shape21(
source: i0.VersionedTable(
entityName: 'remote_asset_cloud_id_entity',
withoutRowId: true,
isStrict: true,
tableConstraints: ['PRIMARY KEY(asset_id)'],
columns: [_column_36, _column_92],
attachedDatabase: database,
),
alias: null,
);
late final Shape11 memoryEntity = Shape11(
source: i0.VersionedTable(
entityName: 'memory_entity',
@@ -4211,22 +4217,8 @@ class Shape20 extends i0.VersionedTable {
columnsByName['checksum']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<bool> get isFavorite =>
columnsByName['is_favorite']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<String> get ownerId =>
columnsByName['owner_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<DateTime> get localDateTime =>
columnsByName['local_date_time']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<String> get thumbHash =>
columnsByName['thumb_hash']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<DateTime> get deletedAt =>
columnsByName['deleted_at']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<String> get livePhotoVideoId =>
columnsByName['live_photo_video_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get visibility =>
columnsByName['visibility']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get stackId =>
columnsByName['stack_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get libraryId =>
columnsByName['library_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get orientation =>
columnsByName['orientation']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get cloudId =>
columnsByName['cloud_id']! as i1.GeneratedColumn<String>;
}
@@ -4241,32 +4233,20 @@ i1.GeneratedColumn<String> _column_91(String aliasedName) =>
class Shape21 extends i0.VersionedTable {
Shape21({required super.source, required super.alias}) : super.aliased();
i1.GeneratedColumn<String> get name =>
columnsByName['name']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<int> get type =>
columnsByName['type']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<DateTime> get createdAt =>
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<DateTime> get updatedAt =>
columnsByName['updated_at']! as i1.GeneratedColumn<DateTime>;
i1.GeneratedColumn<int> get width =>
columnsByName['width']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<int> get height =>
columnsByName['height']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<int> get durationInSeconds =>
columnsByName['duration_in_seconds']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get id =>
columnsByName['id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get checksum =>
columnsByName['checksum']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<bool> get isFavorite =>
columnsByName['is_favorite']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<int> get orientation =>
columnsByName['orientation']! as i1.GeneratedColumn<int>;
i1.GeneratedColumn<String> get assetId =>
columnsByName['asset_id']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get cloudId =>
columnsByName['cloud_id']! as i1.GeneratedColumn<String>;
}
i1.GeneratedColumn<String> _column_92(String aliasedName) =>
i1.GeneratedColumn<String>(
'cloud_id',
aliasedName,
true,
type: i1.DriftSqlType.string,
defaultConstraints: i1.GeneratedColumn.constraintIsAlways('UNIQUE'),
);
i0.MigrationStepWithVersion migrationSteps({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
@@ -75,14 +75,19 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
Future<List<LocalAssetHashMapping>> getHashMappingFromCloudId() async {
final query =
_db.localAssetEntity.selectOnly().join([
leftOuterJoin(
_db.remoteAssetCloudIdEntity,
_db.localAssetEntity.cloudId.equalsExp(_db.remoteAssetCloudIdEntity.cloudId),
useColumns: false,
),
leftOuterJoin(
_db.remoteAssetEntity,
_db.localAssetEntity.cloudId.equalsExp(_db.remoteAssetEntity.cloudId),
_db.remoteAssetCloudIdEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
useColumns: false,
),
])
..addColumns([_db.localAssetEntity.id, _db.remoteAssetEntity.checksum])
..where(_db.remoteAssetEntity.cloudId.isNotNull() & _db.localAssetEntity.checksum.isNull());
..where(_db.remoteAssetCloudIdEntity.cloudId.isNotNull() & _db.localAssetEntity.checksum.isNull());
return query
.map(
(row) => (assetId: row.read(_db.localAssetEntity.id)!, checksum: row.read(_db.remoteAssetEntity.checksum)!),
@@ -15,6 +15,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset_cloud_id.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart';
@@ -183,11 +184,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
await _db.batch((batch) {
for (final metadata in data) {
if (metadata.key == AssetMetadataKey.mobileApp) {
batch.update(
_db.remoteAssetEntity,
const RemoteAssetEntityCompanion(cloudId: Value(null)),
where: (row) => row.id.equals(metadata.assetId),
);
batch.deleteWhere(_db.remoteAssetCloudIdEntity, (row) => row.assetId.equals(metadata.assetId));
}
}
});
@@ -203,10 +200,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
for (final metadata in data) {
if (metadata.key == AssetMetadataKey.mobileApp) {
final map = metadata.value as Map<String, Object?>;
batch.update(
final companion = RemoteAssetCloudIdEntityCompanion(cloudId: Value(map['iCloudId']?.toString()));
batch.insert(
_db.remoteAssetEntity,
RemoteAssetEntityCompanion(cloudId: Value(map['iCloudId']?.toString())),
where: (row) => row.id.equals(metadata.assetId),
companion.copyWith(assetId: Value(metadata.assetId)),
onConflict: DoUpdate((_) => companion),
);
}
}