Files
Immich/mobile/lib/data/db/main/table/remote/asset.dart
T
Santo ShakilandGitHub 909b8aac93 fix(mobile): clamp out of range datetimes so timeline queries cannot crash (#30490)
* fix(mobile): clamp out of range datetimes so timeline queries cannot crash

* replace the per column converters with a clamping custom type

* heal each table in one statement, rename the clamp type, read dates as stored

* one medium test for the clamp, drop the dart side bounds, private clamp type
2026-09-18 17:41:15 +00:00

82 lines
2.8 KiB
Dart

import 'package:drift/drift.dart';
import 'package:immich_mobile/data/db/main/table/remote/asset.drift.dart';
import 'package:immich_mobile/data/db/main/table/user/user.dart';
import 'package:immich_mobile/data/db/util/asset_mixin.dart';
import 'package:immich_mobile/data/db/util/datetime_clamp_type.dart';
import 'package:immich_mobile/data/db/util/defaults_mixin.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
@TableIndex.sql('''
CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum
ON remote_asset_entity (owner_id, checksum)
WHERE (library_id IS NULL);
''')
@TableIndex.sql('''
CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum
ON remote_asset_entity (owner_id, library_id, checksum)
WHERE (library_id IS NOT NULL);
''')
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)')
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_remote_asset_stack_id ON remote_asset_entity (stack_id)')
@TableIndex.sql('''
CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_visibility_deleted_created
ON remote_asset_entity (owner_id, visibility, deleted_at, created_at DESC)
''')
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_remote_asset_uploaded ON remote_asset_entity (uploaded_at)')
class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
const RemoteAssetEntity();
TextColumn get id => text()();
TextColumn get checksum => text()();
BoolColumn get isFavorite => boolean().withDefault(const Constant(false))();
TextColumn get ownerId => text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
DateTimeColumn get localDateTime => customType(clampedDateTime).nullable()();
TextColumn get thumbHash => text().nullable()();
DateTimeColumn get deletedAt => customType(clampedDateTime).nullable()();
DateTimeColumn get uploadedAt => customType(clampedDateTime).nullable()();
TextColumn get livePhotoVideoId => text().nullable()();
IntColumn get visibility => intEnum<AssetVisibility>()();
TextColumn get stackId => text().nullable()();
TextColumn get libraryId => text().nullable()();
BoolColumn get isEdited => boolean().withDefault(const Constant(false))();
@override
Set<Column> get primaryKey => {id};
}
extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
RemoteAsset toDto({String? localId}) => RemoteAsset(
id: id,
name: name,
ownerId: ownerId,
checksum: checksum,
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
uploadedAt: uploadedAt,
durationMs: durationMs,
isFavorite: isFavorite,
height: height,
width: width,
thumbHash: thumbHash,
visibility: visibility,
livePhotoVideoId: livePhotoVideoId,
localId: localId,
stackId: stackId,
isEdited: isEdited,
deletedAt: deletedAt,
);
}