From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 991636DE0B55 for ; Sat, 1 Oct 2016 19:13:38 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.007 X-Spam-Level: X-Spam-Status: No, score=-0.007 tagged_above=-999 required=5 tests=[AWL=0.004, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S-EwjgB-FFXV for ; Sat, 1 Oct 2016 19:13:38 -0700 (PDT) Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197]) by arlo.cworth.org (Postfix) with ESMTPS id 3BC9D6DE098B for ; Sat, 1 Oct 2016 19:13:36 -0700 (PDT) Received: from remotemail by fethera.tethera.net with local (Exim 4.84_2) (envelope-from ) id 1bqWHL-0000LJ-9j; Sat, 01 Oct 2016 22:13:23 -0400 Received: (nullmailer pid 30553 invoked by uid 1000); Sun, 02 Oct 2016 02:13:31 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: [PATCH 4/5] lib: query make exclude handling non-destructive Date: Sat, 1 Oct 2016 23:13:27 -0300 Message-Id: <20161002021328.30487-5-david@tethera.net> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20161002021328.30487-1-david@tethera.net> References: <20161002021328.30487-1-david@tethera.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Oct 2016 02:13:38 -0000 We filter added exclude at add time, rather than modifying the query by count search. As noted in the comments, there are several ignored conditions here. Returning proper status is split into a separate commit because it is ABI breaking. --- lib/query.cc | 48 ++++++++++++++++++++++++++++++------------------ test/T060-count.sh | 1 - 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/query.cc b/lib/query.cc index ba5465d..afbabb6 100644 --- a/lib/query.cc +++ b/lib/query.cc @@ -31,6 +31,7 @@ struct _notmuch_query { notmuch_exclude_t omit_excluded; notmuch_bool_t parsed; Xapian::Query xapian_query; + std::set terms; }; typedef struct _notmuch_mset_messages { @@ -77,6 +78,7 @@ _debug_query (void) static int _notmuch_query_destructor (notmuch_query_t *query) { query->xapian_query.~Query(); + query->terms.~set(); return 0; } @@ -94,6 +96,7 @@ notmuch_query_create (notmuch_database_t *notmuch, return NULL; new (&query->xapian_query) Xapian::Query (); + new (&query->terms) std::set (); query->parsed = FALSE; talloc_set_destructor (query, _notmuch_query_destructor); @@ -121,6 +124,16 @@ _notmuch_query_ensure_parsed (notmuch_query_t *query) query->xapian_query = query->notmuch->query_parser-> parse_query (query->query_string, NOTMUCH_QUERY_PARSER_FLAGS); + + /* Xapian doesn't support skip_to on terms from a query since + * they are unordered, so cache a copy of all terms in + * something searchable. + */ + + for (Xapian::TermIterator t = query->xapian_query.get_terms_begin(); + t != query->xapian_query.get_terms_end(); ++t) + query->terms.insert(*t); + query->parsed = TRUE; } catch (const Xapian::Error &error) { _notmuch_database_log (query->notmuch, @@ -163,7 +176,17 @@ notmuch_query_get_sort (const notmuch_query_t *query) void notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag) { - char *term = talloc_asprintf (query, "%s%s", _find_prefix ("tag"), tag); + notmuch_status_t status; + char *term; + + status = _notmuch_query_ensure_parsed (query); + if (status) + return; /* XXX report error */ + + term = talloc_asprintf (query, "%s%s", _find_prefix ("tag"), tag); + if (query->terms.count(term) != 0) + return; /* XXX report ignoring exclude? */ + _notmuch_string_list_append (query->exclude_terms, term); } @@ -183,28 +206,17 @@ _notmuch_messages_destructor (notmuch_mset_messages_t *messages) } /* Return a query that matches messages with the excluded tags - * registered with query. Any tags that explicitly appear in xquery - * will not be excluded, and will be removed from the list of exclude - * tags. The caller of this function has to combine the returned + * registered with query. The caller of this function has to combine the returned * query appropriately.*/ static Xapian::Query -_notmuch_exclude_tags (notmuch_query_t *query, Xapian::Query xquery) +_notmuch_exclude_tags (notmuch_query_t *query) { Xapian::Query exclude_query = Xapian::Query::MatchNothing; for (notmuch_string_node_t *term = query->exclude_terms->head; term; term = term->next) { - Xapian::TermIterator it = xquery.get_terms_begin (); - Xapian::TermIterator end = xquery.get_terms_end (); - for (; it != end; it++) { - if ((*it).compare (term->string) == 0) - break; - } - if (it == end) - exclude_query = Xapian::Query (Xapian::Query::OP_OR, - exclude_query, Xapian::Query (term->string)); - else - term->string = talloc_strdup (query, ""); + exclude_query = Xapian::Query (Xapian::Query::OP_OR, + exclude_query, Xapian::Query (term->string)); } return exclude_query; } @@ -275,7 +287,7 @@ _notmuch_query_search_documents (notmuch_query_t *query, messages->base.excluded_doc_ids = NULL; if ((query->omit_excluded != NOTMUCH_EXCLUDE_FALSE) && (query->exclude_terms)) { - exclude_query = _notmuch_exclude_tags (query, final_query); + exclude_query = _notmuch_exclude_tags (query); if (query->omit_excluded == NOTMUCH_EXCLUDE_TRUE || query->omit_excluded == NOTMUCH_EXCLUDE_ALL) @@ -630,7 +642,7 @@ _notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsign mail_query, query->xapian_query); } - exclude_query = _notmuch_exclude_tags (query, final_query); + exclude_query = _notmuch_exclude_tags (query); final_query = Xapian::Query (Xapian::Query::OP_AND_NOT, final_query, exclude_query); diff --git a/test/T060-count.sh b/test/T060-count.sh index 69ab591..b82583b 100755 --- a/test/T060-count.sh +++ b/test/T060-count.sh @@ -127,7 +127,6 @@ test_expect_equal_file EXPECTED OUTPUT.clean restore_database test_begin_subtest "count library function is non-destructive" -test_subtest_known_broken cat< EXPECTED 1: 52 messages 2: 52 messages -- 2.9.3