mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Migrate wrong bestDateTime in DB on upgrade
This commit is contained in:
parent
72ebbfdd08
commit
62b28c67a0
2 changed files with 179 additions and 23 deletions
81
app/lib/use_case/compat/v55.dart
Normal file
81
app/lib/use_case/compat/v55.dart
Normal file
|
@ -0,0 +1,81 @@
|
|||
import 'package:drift/drift.dart' as sql;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/entity/sqlite_table.dart' as sql;
|
||||
import 'package:nc_photos/entity/sqlite_table_extension.dart' as sql;
|
||||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class CompatV55 {
|
||||
static Future<void> migrateDb(
|
||||
sql.SqliteDb db, {
|
||||
void Function(int current, int count)? onProgress,
|
||||
}) {
|
||||
return db.use((db) async {
|
||||
final countExp = db.accountFiles.rowId.count();
|
||||
final countQ = db.selectOnly(db.accountFiles)..addColumns([countExp]);
|
||||
final count = await countQ.map((r) => r.read<int>(countExp)).getSingle();
|
||||
onProgress?.call(0, count);
|
||||
|
||||
final needUpdates = <Tuple2<int, DateTime>>[];
|
||||
for (var i = 0; i < count; i += 1000) {
|
||||
final q = db.select(db.files).join([
|
||||
sql.innerJoin(
|
||||
db.accountFiles, db.accountFiles.file.equalsExp(db.files.rowId)),
|
||||
sql.innerJoin(db.images,
|
||||
db.images.accountFile.equalsExp(db.accountFiles.rowId)),
|
||||
]);
|
||||
q
|
||||
..orderBy([
|
||||
sql.OrderingTerm(
|
||||
expression: db.accountFiles.rowId,
|
||||
mode: sql.OrderingMode.asc,
|
||||
),
|
||||
])
|
||||
..limit(1000, offset: i);
|
||||
final dbFiles = await q
|
||||
.map((r) => sql.CompleteFile(
|
||||
r.readTable(db.files),
|
||||
r.readTable(db.accountFiles),
|
||||
r.readTable(db.images),
|
||||
null,
|
||||
null,
|
||||
))
|
||||
.get();
|
||||
for (final f in dbFiles) {
|
||||
final bestDateTime = file_util.getBestDateTime(
|
||||
overrideDateTime: f.accountFile.overrideDateTime,
|
||||
dateTimeOriginal: f.image?.dateTimeOriginal,
|
||||
lastModified: f.file.lastModified,
|
||||
);
|
||||
if (f.accountFile.bestDateTime != bestDateTime) {
|
||||
// need update
|
||||
needUpdates.add(Tuple2(f.accountFile.rowId, bestDateTime));
|
||||
}
|
||||
}
|
||||
onProgress?.call(i, count);
|
||||
}
|
||||
|
||||
_log.info("[migrateDb] ${needUpdates.length} rows require updating");
|
||||
if (kDebugMode) {
|
||||
_log.fine(
|
||||
"[migrateDb] ${needUpdates.map((e) => e.item1).toReadableString()}");
|
||||
}
|
||||
await db.batch((batch) {
|
||||
for (final pair in needUpdates) {
|
||||
batch.update(
|
||||
db.accountFiles,
|
||||
sql.AccountFilesCompanion(
|
||||
bestDateTime: sql.Value(pair.item2),
|
||||
),
|
||||
where: (sql.$AccountFilesTable table) =>
|
||||
table.rowId.equals(pair.item1),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static final _log = Logger("use_case.compat.v55.CompatV55");
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:kiwi/kiwi.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/entity/sqlite_table_extension.dart' as sql;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/mobile/android/activity.dart';
|
||||
import 'package:nc_photos/platform/k.dart' as platform_k;
|
||||
|
@ -12,6 +14,7 @@ import 'package:nc_photos/pref.dart';
|
|||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/compat/v29.dart';
|
||||
import 'package:nc_photos/use_case/compat/v46.dart';
|
||||
import 'package:nc_photos/use_case/compat/v55.dart';
|
||||
import 'package:nc_photos/widget/changelog.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/setup.dart';
|
||||
|
@ -68,10 +71,11 @@ class _SplashState extends State<Splash> {
|
|||
Widget _buildContent(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
@ -88,25 +92,36 @@ class _SplashState extends State<Splash> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (_isUpgrading)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 64,
|
||||
child: Column(
|
||||
children: const [
|
||||
SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text("Updating"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_isUpgrading)
|
||||
BlocBuilder<_UpgradeCubit, _UpgradeState>(
|
||||
bloc: _upgradeCubit,
|
||||
builder: (context, state) {
|
||||
return Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 64,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(state.text),
|
||||
const SizedBox(height: 8),
|
||||
if (state.count == null)
|
||||
const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
else
|
||||
LinearProgressIndicator(
|
||||
value: state.current / state.count!,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -164,6 +179,9 @@ class _SplashState extends State<Splash> {
|
|||
if (lastVersion < 460) {
|
||||
await _upgrade46(lastVersion);
|
||||
}
|
||||
if (lastVersion < 550) {
|
||||
await _upgrade55(lastVersion);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _upgrade29(int lastVersion) async {
|
||||
|
@ -204,6 +222,33 @@ class _SplashState extends State<Splash> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _upgrade55(int lastVersion) async {
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
try {
|
||||
_log.info("[_upgrade55] migrate DB");
|
||||
await CompatV55.migrateDb(
|
||||
c.sqliteDb,
|
||||
onProgress: (current, count) {
|
||||
_upgradeCubit.setState(
|
||||
L10n.global().migrateDatabaseProcessingNotification,
|
||||
current,
|
||||
count,
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout("[_upgrade55] Failed while migrateDb", e, stackTrace);
|
||||
await c.sqliteDb.use((db) async {
|
||||
await db.truncate();
|
||||
final accounts = Pref().getAccounts3Or([]);
|
||||
for (final a in accounts) {
|
||||
await db.insertAccountOf(a);
|
||||
}
|
||||
});
|
||||
}
|
||||
_upgradeCubit.setIntermediate();
|
||||
}
|
||||
|
||||
Future<void> _showChangelogIfAvailable(int lastVersion) async {
|
||||
if (Changelog.hasContent(lastVersion)) {
|
||||
try {
|
||||
|
@ -222,6 +267,36 @@ class _SplashState extends State<Splash> {
|
|||
|
||||
final _changelogCompleter = Completer();
|
||||
var _isUpgrading = false;
|
||||
late final _upgradeCubit = _UpgradeCubit();
|
||||
|
||||
static final _log = Logger("widget.splash._SplashState");
|
||||
}
|
||||
|
||||
class _UpgradeState {
|
||||
const _UpgradeState(String text, int current, int count)
|
||||
: this._(text, current, count);
|
||||
|
||||
const _UpgradeState.intermediate([String? text])
|
||||
: this._(text ?? "Updating", 0, null);
|
||||
|
||||
const _UpgradeState._(this.text, this.current, this.count);
|
||||
|
||||
@override
|
||||
String toString() => "_UpgradeState {"
|
||||
"current: $current, "
|
||||
"count: $count, "
|
||||
"}";
|
||||
|
||||
final String text;
|
||||
final int current;
|
||||
final int? count;
|
||||
}
|
||||
|
||||
class _UpgradeCubit extends Cubit<_UpgradeState> {
|
||||
_UpgradeCubit() : super(const _UpgradeState.intermediate());
|
||||
|
||||
void setIntermediate() => emit(const _UpgradeState.intermediate());
|
||||
|
||||
void setState(String text, int current, int count) =>
|
||||
emit(_UpgradeState(text, current, count));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue