[geary/mjog/search-refinement: 4/14] Add Geary.Account::list_local_email_async
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/search-refinement: 4/14] Add Geary.Account::list_local_email_async
- Date: Mon, 16 Dec 2019 23:11:14 +0000 (UTC)
commit b3488f6cf93b22e65e46303e1a2a921cd213b33c
Author: Michael Gratton <mike vee net>
Date: Tue Dec 10 13:36:36 2019 +1100
Add Geary.Account::list_local_email_async
Add new method and implementation to support breaking search folder
impl out of the ImapDb package.
src/engine/api/geary-account.vala | 16 ++++++
src/engine/imap-db/imap-db-account.vala | 42 ++++++++++++++++
.../imap-engine/imap-engine-generic-account.vala | 23 ++++++---
test/engine/api/geary-account-mock.vala | 12 +++++
test/engine/imap-db/imap-db-account-test.vala | 57 ++++++++++++++++++++++
5 files changed, 144 insertions(+), 6 deletions(-)
---
diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala
index 0bb90aba..54b1d9db 100644
--- a/src/engine/api/geary-account.vala
+++ b/src/engine/api/geary-account.vala
@@ -425,6 +425,22 @@ public abstract class Geary.Account : BaseObject, Logging.Source {
public abstract async Geary.Email local_fetch_email_async(Geary.EmailIdentifier email_id,
Geary.Email.Field required_fields, Cancellable? cancellable = null) throws Error;
+ /**
+ * Return a collection of email with the given identifiers.
+ *
+ * The returned collection will be in the same order as the
+ * natural ordering of the given identifiers.
+ *
+ * Throws {@link EngineError.NOT_FOUND} if any email is not found
+ * and {@link EngineError.INCOMPLETE_MESSAGE} if the fields aren't
+ * available.
+ */
+ public abstract async Gee.List<Email> list_local_email_async(
+ Gee.Collection<EmailIdentifier> ids,
+ Email.Field required_fields,
+ GLib.Cancellable? cancellable = null
+ ) throws GLib.Error;
+
/**
* Create a new {@link SearchQuery} for this {@link Account}.
*
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index c50a7b5a..59c60125 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -804,6 +804,48 @@ private class Geary.ImapDB.Account : BaseObject {
return search_matches;
}
+ public async Gee.List<Email>? list_email(Gee.Collection<EmailIdentifier> ids,
+ Email.Field required_fields,
+ GLib.Cancellable? cancellable = null)
+ throws GLib.Error {
+ check_open();
+
+ var results = new Gee.ArrayList<Email>();
+ yield db.exec_transaction_async(Db.TransactionType.RO, (cx) => {
+ foreach (var id in ids) {
+ // TODO: once we have a way of deleting messages, we won't be able
+ // to assume that a row id will point to the same email outside of
+ // transactions, because SQLite will reuse row ids.
+ Geary.Email.Field db_fields;
+ MessageRow row = Geary.ImapDB.Folder.do_fetch_message_row(
+ cx, id.message_id, required_fields, out db_fields, cancellable
+ );
+ if (!row.fields.fulfills(required_fields)) {
+ throw new EngineError.INCOMPLETE_MESSAGE(
+ "Message %s only fulfills %Xh fields (required: %Xh)",
+ id.to_string(), row.fields, required_fields
+ );
+ }
+
+ Email email = row.to_email(id);
+ Attachment.add_attachments(
+ cx,
+ this.db.attachments_path,
+ email,
+ id.message_id,
+ cancellable
+ );
+
+ results.add(email);
+ }
+ return Db.TransactionOutcome.DONE;
+ },
+ cancellable
+ );
+
+ return results;
+ }
+
public async Geary.Email fetch_email_async(ImapDB.EmailIdentifier email_id,
Geary.Email.Field required_fields, Cancellable? cancellable = null) throws Error {
check_open();
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 4edcc80e..7599ee06 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -512,6 +512,16 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
return (Gee.Collection<ImapDB.EmailIdentifier>) ids;
}
+ /** {@inheritDoc} */
+ public override async SearchQuery new_search_query(string query,
+ SearchQuery.Strategy strategy,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
+ return yield new ImapDB.SearchQuery(
+ this, local, query, strategy, cancellable
+ );
+ }
+
public override async Gee.MultiMap<Geary.Email, Geary.FolderPath?>? local_search_message_id_async(
Geary.RFC822.MessageID message_id, Geary.Email.Field requested_fields, bool partial_ok,
Gee.Collection<Geary.FolderPath?>? folder_blacklist, Geary.EmailFlags? flag_blacklist,
@@ -526,12 +536,13 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
}
/** {@inheritDoc} */
- public override async SearchQuery new_search_query(string query,
- SearchQuery.Strategy strategy,
- GLib.Cancellable? cancellable)
- throws GLib.Error {
- return yield new ImapDB.SearchQuery(
- this, local, query, strategy, cancellable
+ public override async Gee.List<Email> list_local_email_async(
+ Gee.Collection<EmailIdentifier> ids,
+ Email.Field required_fields,
+ GLib.Cancellable? cancellable = null
+ ) throws GLib.Error {
+ return yield local.list_email(
+ check_ids(ids), required_fields, cancellable
);
}
diff --git a/test/engine/api/geary-account-mock.vala b/test/engine/api/geary-account-mock.vala
index 07551eb1..9f074d62 100644
--- a/test/engine/api/geary-account-mock.vala
+++ b/test/engine/api/geary-account-mock.vala
@@ -204,6 +204,18 @@ public class Geary.MockAccount : Account, MockObject {
);
}
+ public override async Gee.List<Email> list_local_email_async(
+ Gee.Collection<EmailIdentifier> ids,
+ Email.Field required_fields,
+ GLib.Cancellable? cancellable = null
+ ) throws GLib.Error {
+ return object_or_throw_call<Gee.List<Email>>(
+ "list_local_email_async",
+ {ids, box_arg(required_fields), cancellable},
+ new EngineError.NOT_FOUND("Mock call")
+ );
+ }
+
public override async Email local_fetch_email_async(EmailIdentifier email_id,
Email.Field required_fields,
Cancellable? cancellable = null)
diff --git a/test/engine/imap-db/imap-db-account-test.vala b/test/engine/imap-db/imap-db-account-test.vala
index a82fb1ce..3d1e90ab 100644
--- a/test/engine/imap-db/imap-db-account-test.vala
+++ b/test/engine/imap-db/imap-db-account-test.vala
@@ -26,6 +26,7 @@ class Geary.ImapDB.AccountTest : TestCase {
add_test("fetch_base_folder", fetch_base_folder);
add_test("fetch_child_folder", fetch_child_folder);
add_test("fetch_nonexistent_folder", fetch_nonexistent_folder);
+ add_test("list_local_email", list_local_email);
}
public override void set_up() throws GLib.Error {
@@ -310,4 +311,60 @@ class Geary.ImapDB.AccountTest : TestCase {
}
}
+ public void list_local_email() throws GLib.Error {
+ Email.Field fixture_fields = Email.Field.RECEIVERS;
+ string fixture_to = "test1 example com";
+ this.account.db.exec(
+ "INSERT INTO MessageTable (id, fields, to_field) " +
+ "VALUES (1, %d, '%s');".printf(fixture_fields, fixture_to)
+ );
+ this.account.db.exec(
+ "INSERT INTO MessageTable (id, fields, to_field) " +
+ "VALUES (2, %d, '%s');".printf(fixture_fields, fixture_to)
+ );
+
+ this.account.list_email.begin(
+ iterate_array<Geary.ImapDB.EmailIdentifier>({
+ new EmailIdentifier(1, null),
+ new EmailIdentifier(2, null)
+ }).to_linked_list(),
+ Email.Field.RECEIVERS,
+ null,
+ (obj, ret) => { async_complete(ret); }
+ );
+ Gee.List<Email> result = this.account.list_email.end(
+ async_result()
+ );
+
+ assert_int(2, result.size, "Not enough email listed");
+ assert_true(new EmailIdentifier(1, null).equal_to(result[0].id));
+ assert_true(new EmailIdentifier(2, null).equal_to(result[1].id));
+
+ this.account.list_email.begin(
+ Collection.single(new EmailIdentifier(3, null)),
+ Email.Field.RECEIVERS,
+ null,
+ (obj, ret) => { async_complete(ret); }
+ );
+ try {
+ this.account.list_email.end(async_result());
+ assert_not_reached();
+ } catch (EngineError.NOT_FOUND error) {
+ // All good
+ }
+
+ this.account.list_email.begin(
+ Collection.single(new EmailIdentifier(1, null)),
+ Email.Field.BODY,
+ null,
+ (obj, ret) => { async_complete(ret); }
+ );
+ try {
+ this.account.list_email.end(async_result());
+ assert_not_reached();
+ } catch (EngineError.INCOMPLETE_MESSAGE error) {
+ // All good
+ }
+ }
+
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]