[geary/mjog/mail-merge-plugin: 49/72] Geary.Folder: Add new contains_identifiers method




commit 910228093cd50cb62f73475f013e6a8ee6119846
Author: Michael Gratton <mike vee net>
Date:   Wed Aug 5 14:07:43 2020 +1000

    Geary.Folder: Add new contains_identifiers method
    
    Add new public method that allows API clients to query whether a folder
    contains a specific set of email ids. Add implementation to all
    derived classes.

 .../plugin/mail-merge/mail-merge-folder.vala       | 12 ++++++
 src/engine/api/geary-folder.vala                   | 14 +++++++
 src/engine/app/app-search-folder.vala              | 12 ++++++
 src/engine/imap-db/imap-db-folder.vala             | 49 ++++++++++++++++++++++
 .../imap-engine/imap-engine-minimal-folder.vala    |  9 ++++
 src/engine/outbox/outbox-folder.vala               | 28 +++++++++++++
 test/mock/mock-folder.vala                         | 11 +++++
 7 files changed, 135 insertions(+)
---
diff --git a/src/client/plugin/mail-merge/mail-merge-folder.vala 
b/src/client/plugin/mail-merge/mail-merge-folder.vala
index 0a15743aa..c07e009f9 100644
--- a/src/client/plugin/mail-merge/mail-merge-folder.vala
+++ b/src/client/plugin/mail-merge/mail-merge-folder.vala
@@ -141,6 +141,18 @@ public class Plugin.MailMergeFolder : Geary.AbstractLocalFolder {
         );
     }
 
+    /** {@inheritDoc} */
+    public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        return Geary.traverse(
+            ids
+        ).filter(
+            (id) => this.map.has_key(id)
+        ).to_hash_set();
+    }
+
     public override async Geary.Email
         fetch_email_async(Geary.EmailIdentifier id,
                           Geary.Email.Field required_fields,
diff --git a/src/engine/api/geary-folder.vala b/src/engine/api/geary-folder.vala
index 89a940fd1..587014273 100644
--- a/src/engine/api/geary-folder.vala
+++ b/src/engine/api/geary-folder.vala
@@ -626,6 +626,20 @@ public abstract class Geary.Folder : BaseObject, Logging.Source {
     public abstract async void synchronise_remote(GLib.Cancellable? cancellable)
         throws GLib.Error;
 
+    /**
+     * Determines the email identifiers that are contained in the folder.
+     *
+     * The returned collection will be a subset of the given input
+     * collection that contains an input identifier only if that
+     * identifier belongs to an email contained by the folder.
+     *
+     * The Folder must be opened prior to attempting this operation.
+     */
+    public abstract async Gee.Collection<EmailIdentifier> contains_identifiers(
+        Gee.Collection<EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error;
+
     /**
      * List a number of contiguous emails in the folder's vector.
      *
diff --git a/src/engine/app/app-search-folder.vala b/src/engine/app/app-search-folder.vala
index 85c8c75c6..0ad7552f2 100644
--- a/src/engine/app/app-search-folder.vala
+++ b/src/engine/app/app-search-folder.vala
@@ -213,6 +213,18 @@ public class Geary.App.SearchFolder :
         return results;
     }
 
+    /** {@inheritDoc} */
+    public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        return Geary.traverse(
+            ids
+        ).filter(
+            (id) => this.id_map.has_key(id)
+        ).to_hash_set();
+    }
+
     public override async Gee.List<Email>? list_email_by_id_async(
         EmailIdentifier? initial_id,
         int count,
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index bcb41d6ae..3960a0721 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -341,6 +341,55 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
         return results;
     }
 
+    /** Returns a subset of the given ids that are in this folder. */
+    public async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        var contained_ids = new Gee.HashMap<int64?,EmailIdentifier>(
+            Collection.int64_hash_func,
+            Collection.int64_equal_func
+        );
+        if (!ids.is_empty) {
+            var valid_ids = new Gee.HashMap<int64?,EmailIdentifier>(
+                Collection.int64_hash_func,
+                Collection.int64_equal_func
+            );
+            yield db.exec_transaction_async(
+                RO,
+                (cx, cancellable) => {
+                    var sql = new StringBuilder("""
+                        SELECT message_id
+                        FROM MessageLocationTable
+                        WHERE message_id IN (
+                    """);
+                    foreach (var id in ids) {
+                        var id_impl = id as EmailIdentifier;
+                        if (id_impl != null) {
+                            sql.append(id_impl.message_id.to_string());
+                            valid_ids.set(id_impl.message_id, id_impl);
+                        }
+                    }
+                    sql.append(") AND folder_id=? AND remove_marker<>?");
+
+                    Db.Statement stmt = cx.prepare(sql.str);
+                    stmt.bind_rowid(0, this.folder_id);
+                    stmt.bind_bool(0, false);
+
+                    Db.Result results = stmt.exec(cancellable);
+                    while (!results.finished) {
+                        var message_id = results.int64_at(0);
+                        contained_ids.set(message_id, valid_ids.get(message_id));
+                        results.next(cancellable);
+                    }
+                    return COMMIT;
+                },
+                cancellable
+            );
+        }
+        return contained_ids.values;
+    }
+
     public async Gee.List<Geary.Email>? list_email_by_id_async(ImapDB.EmailIdentifier? initial_id,
         int count, Geary.Email.Field required_fields, ListFlags flags, Cancellable? cancellable)
         throws Error {
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index a9905b696..231591474 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -1201,6 +1201,15 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         this.replay_queue.schedule_server_notification(op);
     }
 
+    /** {@inheritDoc} */
+    public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        check_open("contains_identifiers");
+        return yield this.local_folder.contains_identifiers(ids, cancellable);
+    }
+
     //
     // list email variants
     //
diff --git a/src/engine/outbox/outbox-folder.vala b/src/engine/outbox/outbox-folder.vala
index 6e4024777..9fb84c2b8 100644
--- a/src/engine/outbox/outbox-folder.vala
+++ b/src/engine/outbox/outbox-folder.vala
@@ -210,6 +210,34 @@ public class Geary.Outbox.Folder :
         }
     }
 
+    /** {@inheritDoc} */
+    public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        check_open();
+        var contains = new Gee.HashSet<Geary.EmailIdentifier>();
+        yield db.exec_transaction_async(
+            RO,
+            (cx, cancellable) => {
+                foreach (Geary.EmailIdentifier id in ids) {
+                    var outbox_id = id as EmailIdentifier;
+                    if (outbox_id != null) {
+                        var row = do_fetch_row_by_ordering(
+                            cx, outbox_id.ordering, cancellable
+                        );
+                        if (row != null) {
+                            contains.add(id);
+                        }
+                    }
+                }
+                return DONE;
+            },
+            cancellable
+        );
+        return contains;
+    }
+
     public override async Gee.List<Email>?
         list_email_by_id_async(Geary.EmailIdentifier? _initial_id,
                                int count,
diff --git a/test/mock/mock-folder.vala b/test/mock/mock-folder.vala
index 52d100ba5..59e5a220d 100644
--- a/test/mock/mock-folder.vala
+++ b/test/mock/mock-folder.vala
@@ -85,6 +85,17 @@ public class Mock.Folder : Geary.Folder,
         void_call("synchronise_remote", { cancellable });
     }
 
+    public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
+        Gee.Collection<Geary.EmailIdentifier> ids,
+        GLib.Cancellable? cancellable = null)
+    throws GLib.Error {
+        return yield object_call_async<Gee.Collection<Geary.EmailIdentifier>>(
+            "contains_identifiers",
+            {ids, cancellable},
+            new Gee.LinkedList<Geary.EmailIdentifier>()
+        );
+    }
+
     public override async Gee.List<Geary.Email>?
         list_email_by_id_async(Geary.EmailIdentifier? initial_id,
                                int count,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]