Fix account not deleted from db after signing out

This commit is contained in:
Ming Ming 2022-07-16 02:10:08 +08:00
parent d85ed4102b
commit 878699b02c
3 changed files with 68 additions and 25 deletions

View file

@ -157,7 +157,7 @@ class FileSqliteCacheUpdater {
if (diff.item2.isNotEmpty) { if (diff.item2.isNotEmpty) {
// delete obsolete children // delete obsolete children
await _removeSqliteFiles(db, dbAccount, diff.item2); await _removeSqliteFiles(db, dbAccount, diff.item2);
await _cleanUpRemovedFile(db, dbAccount); await db.cleanUpDanglingFiles();
} }
}); });
} }
@ -313,7 +313,7 @@ class FileSqliteCacheRemover {
final dbAccount = await db.accountOf(account); final dbAccount = await db.accountOf(account);
final rowIds = await db.accountFileRowIdsOf(f, sqlAccount: dbAccount); final rowIds = await db.accountFileRowIdsOf(f, sqlAccount: dbAccount);
await _removeSqliteFiles(db, dbAccount, [rowIds.fileRowId]); await _removeSqliteFiles(db, dbAccount, [rowIds.fileRowId]);
await _cleanUpRemovedFile(db, dbAccount); await db.cleanUpDanglingFiles();
}); });
} }
@ -340,7 +340,7 @@ class FileSqliteCacheEmptier {
childIds.removeWhere((id) => id == rowIds.fileRowId); childIds.removeWhere((id) => id == rowIds.fileRowId);
if (childIds.isNotEmpty) { if (childIds.isNotEmpty) {
await _removeSqliteFiles(db, dbAccount, childIds); await _removeSqliteFiles(db, dbAccount, childIds);
await _cleanUpRemovedFile(db, dbAccount); await db.cleanUpDanglingFiles();
} }
// remove dir in DirFiles // remove dir in DirFiles
@ -380,25 +380,3 @@ Future<void> _removeSqliteFiles(
return; return;
} }
} }
Future<void> _cleanUpRemovedFile(sql.SqliteDb db, sql.Account dbAccount) async {
// delete dangling files: entries in Files w/o a corresponding entry in
// AccountFiles
final danglingFileQuery = db.selectOnly(db.files).join([
sql.leftOuterJoin(
db.accountFiles, db.accountFiles.file.equalsExp(db.files.rowId),
useColumns: false),
])
..addColumns([db.files.rowId])
..where(db.accountFiles.relativePath.isNull());
final danglingFileRowIds =
await danglingFileQuery.map((r) => r.read(db.files.rowId)!).get();
if (danglingFileRowIds.isNotEmpty) {
__log.info(
"[_cleanUpRemovedFile] Delete ${danglingFileRowIds.length} files");
await (db.delete(db.files)..where((t) => t.rowId.isIn(danglingFileRowIds)))
.go();
}
}
final __log = Logger("entity.file.file_cache_manager");

View file

@ -1,4 +1,5 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart' as app; import 'package:nc_photos/account.dart' as app;
import 'package:nc_photos/entity/file.dart' as app; import 'package:nc_photos/entity/file.dart' as app;
import 'package:nc_photos/entity/sqlite_table.dart'; import 'package:nc_photos/entity/sqlite_table.dart';
@ -158,6 +159,45 @@ extension SqliteDbExtension on SqliteDb {
return query.map((r) => r.readTable(accounts)).getSingle(); return query.map((r) => r.readTable(accounts)).getSingle();
} }
/// Delete Account by app Account
///
/// If the deleted Account is the last one associated with a Server, then the
/// Server will also be deleted
Future<void> deleteAccountOf(app.Account account) async {
final dbAccount = await accountOf(account);
_log.info("[deleteAccountOf] Remove account: ${dbAccount.rowId}");
await (delete(accounts)..where((t) => t.rowId.equals(dbAccount.rowId)))
.go();
final accountCountExp =
accounts.rowId.count(filter: accounts.server.equals(dbAccount.server));
final accountCountQuery = selectOnly(accounts)
..addColumns([accountCountExp]);
final accountCount =
await accountCountQuery.map((r) => r.read(accountCountExp)).getSingle();
_log.info("[deleteAccountOf] Remaining accounts in server: $accountCount");
if (accountCount == 0) {
_log.info("[deleteAccountOf] Remove server: ${dbAccount.server}");
await (delete(servers)..where((t) => t.rowId.equals(dbAccount.server)))
.go();
}
await cleanUpDanglingFiles();
}
/// Delete Files without a corresponding entry in AccountFiles
Future<void> cleanUpDanglingFiles() async {
final query = selectOnly(files).join([
leftOuterJoin(accountFiles, accountFiles.file.equalsExp(files.rowId),
useColumns: false),
])
..addColumns([files.rowId])
..where(accountFiles.relativePath.isNull());
final fileRowIds = await query.map((r) => r.read(files.rowId)!).get();
if (fileRowIds.isNotEmpty) {
_log.info("[cleanUpDanglingFiles] Delete ${fileRowIds.length} files");
await (delete(files)..where((t) => t.rowId.isIn(fileRowIds))).go();
}
}
FilesQueryBuilder queryFiles() => FilesQueryBuilder(this); FilesQueryBuilder queryFiles() => FilesQueryBuilder(this);
/// Query File by app File /// Query File by app File
@ -346,6 +386,8 @@ extension SqliteDbExtension on SqliteDb {
)) ))
.get(); .get();
} }
static final _log = Logger("entity.sqlite_table_extension.SqliteDbExtension");
} }
enum FilesQueryMode { enum FilesQueryMode {

View file

@ -1,7 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart'; import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_localizations.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/exception_util.dart' as exception_util; import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/pref.dart'; import 'package:nc_photos/pref.dart';
@ -154,6 +157,26 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
Pref() Pref()
..setAccounts3(accounts) ..setAccounts3(accounts)
..setCurrentAccountIndex(newAccountIndex); ..setCurrentAccountIndex(newAccountIndex);
// check if the same account (server + userId) still exists in known
// accounts
if (!accounts
.any((a) => a.url == account.url && a.userId == account.userId)) {
// account removed, clear cache db
await _removeAccountFromDb(account);
}
}
Future<void> _removeAccountFromDb(Account account) async {
try {
final c = KiwiContainer().resolve<DiContainer>();
await c.sqliteDb.use((db) async {
await db.deleteAccountOf(account);
});
} catch (e, stackTrace) {
_log.shout("[_removeAccountFromDb] Failed while removing account from db",
e, stackTrace);
}
} }
late List<Account> _accounts; late List<Account> _accounts;