From cecf66df08c488a726a9379fc72a0694de4f1e23 Mon Sep 17 00:00:00 2001 From: Chris Heywood <15127-creywood@users.noreply.gitlab.gnome.org> Date: Wed, 8 Jan 2020 11:31:25 +0100 Subject: [PATCH] Track and notify messages detached during cleanup Split detach query into two so that messages identifiers can be captured which are then used to signal through that the folder has locally removed messages --- src/engine/imap-db/imap-db-folder.vala | 49 ++++++++++++++++--- .../imap-engine-account-synchronizer.vala | 5 +- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala index 489dc908..b6ff465c 100644 --- a/src/engine/imap-db/imap-db-folder.vala +++ b/src/engine/imap-db/imap-db-folder.vala @@ -882,16 +882,18 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { }, cancellable); } - public async void detach_emails_before_timestamp(DateTime cutoff, + public async Gee.Collection? detach_emails_before_timestamp(DateTime cutoff, Cancellable? cancellable) throws Error { debug("Detaching emails before %s for folder ID %", cutoff.to_string(), this.folder_id.to_string()); + Gee.Collection? deleted_ids = null; yield db.exec_transaction_async(Db.TransactionType.WO, (cx) => { - // Query was found to be faster than other approaches. MessageLocationTable.ordering - // isn't relied on due to IMAP folder UIDs not guaranteed to be in order. + // MessageLocationTable.ordering isn't relied on due to IMAP folder + // UIDs not guaranteed to be in order. StringBuilder sql = new StringBuilder(); sql.append(""" - DELETE FROM MessageLocationTable + SELECT id, message_id, ordering + FROM MessageLocationTable WHERE folder_id = ? AND message_id IN ( SELECT id @@ -902,12 +904,45 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { """); Db.Statement stmt = cx.prepare(sql.str); - stmt.bind_rowid(0, this.folder_id); + stmt.bind_rowid(0, folder_id); stmt.bind_int64(1, cutoff.to_unix()); - stmt.exec(cancellable); - return Db.TransactionOutcome.COMMIT; + Db.Result results = stmt.exec(cancellable); + + StringBuilder? ids_sql_sublist = null; + while (!results.finished) { + if (ids_sql_sublist == null) { + deleted_ids = new Gee.ArrayList(); + ids_sql_sublist = new StringBuilder(); + } else { + ids_sql_sublist.append(","); + } + + deleted_ids.add(new ImapDB.EmailIdentifier(results.int64_at(1), new Imap.UID(results.int64_at(2)))); + ids_sql_sublist.append(results.rowid_at(0).to_string()); + + results.next(cancellable); + } + + if (deleted_ids != null) { + sql = new StringBuilder(); + sql.append(""" + DELETE FROM MessageLocationTable + WHERE id IN ( + """); + sql.append(ids_sql_sublist.str); + sql.append(")"); + stmt = cx.prepare(sql.str); + + stmt.exec(cancellable); + + return Db.TransactionOutcome.COMMIT; + } else { + return Db.TransactionOutcome.DONE; + } }, cancellable); + + return deleted_ids; } public async void mark_email_async(Gee.Collection to_mark, diff --git a/src/engine/imap-engine/imap-engine-account-synchronizer.vala b/src/engine/imap-engine/imap-engine-account-synchronizer.vala index f0f2b84c..654ca039 100644 --- a/src/engine/imap-engine/imap-engine-account-synchronizer.vala +++ b/src/engine/imap-engine/imap-engine-account-synchronizer.vala @@ -247,7 +247,10 @@ private class Geary.ImapEngine.CheckFolderSync : RefreshFolderSync { // Detach older emails outside the prefetch window if (this.account.information.prefetch_period_days >= 0) { - yield local_folder.detach_emails_before_timestamp(prefetch_max_epoch, cancellable); + Gee.Collection? detached_ids = yield local_folder.detach_emails_before_timestamp(prefetch_max_epoch, cancellable); + if (detached_ids != null) { + this.folder.email_locally_removed(detached_ids); + } } // get oldest local email and its time, as well as number