1 Return-Path: <amdragon@mit.edu>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 780CA429E21
\r
6 for <notmuch@notmuchmail.org>; Wed, 11 Jan 2012 10:48:35 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5
\r
12 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id NvGxMEIV7LhK for <notmuch@notmuchmail.org>;
\r
16 Wed, 11 Jan 2012 10:48:34 -0800 (PST)
\r
17 Received: from dmz-mailsec-scanner-6.mit.edu (DMZ-MAILSEC-SCANNER-6.MIT.EDU
\r
19 by olra.theworths.org (Postfix) with ESMTP id 73D8D431FB6
\r
20 for <notmuch@notmuchmail.org>; Wed, 11 Jan 2012 10:48:34 -0800 (PST)
\r
21 X-AuditID: 12074423-b7f9c6d0000008c3-a7-4f0dd9824e6c
\r
22 Received: from mailhub-auth-4.mit.edu ( [18.7.62.39])
\r
23 by dmz-mailsec-scanner-6.mit.edu (Symantec Messaging Gateway) with SMTP
\r
24 id 42.EC.02243.289DD0F4; Wed, 11 Jan 2012 13:48:34 -0500 (EST)
\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])
\r
26 by mailhub-auth-4.mit.edu (8.13.8/8.9.2) with ESMTP id q0BImXt0013787;
\r
27 Wed, 11 Jan 2012 13:48:34 -0500
\r
28 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])
\r
29 (authenticated bits=0)
\r
30 (User authenticated as amdragon@ATHENA.MIT.EDU)
\r
31 by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q0BImWho011482
\r
32 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);
\r
33 Wed, 11 Jan 2012 13:48:33 -0500 (EST)
\r
34 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.77)
\r
35 (envelope-from <amdragon@mit.edu>)
\r
36 id 1Rl3Dy-0004ET-Gz; Wed, 11 Jan 2012 13:48:38 -0500
\r
37 Date: Wed, 11 Jan 2012 13:48:38 -0500
\r
38 From: Austin Clements <amdragon@MIT.EDU>
\r
39 To: Jani Nikula <jani@nikula.org>
\r
40 Subject: Re: [PATCH 2/3] lib: Add support for automatically excluding tags
\r
42 Message-ID: <20120111184838.GT20796@mit.edu>
\r
43 References: <20120109043101.GH20796@mit.edu>
\r
44 <1326258173-21163-1-git-send-email-amdragon@mit.edu>
\r
45 <1326258173-21163-3-git-send-email-amdragon@mit.edu>
\r
46 <87ty42v99m.fsf@nikula.org>
\r
48 Content-Type: text/plain; charset=us-ascii
\r
49 Content-Disposition: inline
\r
50 In-Reply-To: <87ty42v99m.fsf@nikula.org>
\r
51 User-Agent: Mutt/1.5.21 (2010-09-15)
\r
52 X-Brightmail-Tracker:
\r
53 H4sIAAAAAAAAA+NgFmphleLIzCtJLcpLzFFi42IRYrdT1226yetv8G0Fu0XTdGeL6zdnMjsw
\r
54 edy6/5rd49mqW8wBTFFcNimpOZllqUX6dglcGTsWnGcqWGBYcfVdJ1MD41m1LkZODgkBE4n1
\r
55 7/pYIGwxiQv31rN1MXJxCAnsY5RY19vICOFsYJR49vUlVOYkk8SRd49ZIJwljBJzXj0D62cR
\r
56 UJXYPekuG4jNJqAhsW3/ckYQW0RAUWLzyf1gNrOAtMS3381MILawQKTEh01/2UFsXgEdidub
\r
57 dkGt28EoceXKVWaIhKDEyZlPWCCatSRu/HsJ1MwBNmj5Pw6QMCfQrr2TF4LNERVQkZhychvb
\r
58 BEahWUi6ZyHpnoXQvYCReRWjbEpulW5uYmZOcWqybnFyYl5eapGumV5uZoleakrpJkZwYLso
\r
59 72D8c1DpEKMAB6MSD++Ovbz+QqyJZcWVuYcYJTmYlER5V90ACvEl5adUZiQWZ8QXleakFh9i
\r
60 lOBgVhLhdaoByvGmJFZWpRblw6SkOViUxHk1tN75CQmkJ5akZqemFqQWwWRlODiUJHg3ggwV
\r
61 LEpNT61Iy8wpQUgzcXCCDOcBGr4cpIa3uCAxtzgzHSJ/ilFRSpx3EkhCACSRUZoH1wtLPK8Y
\r
62 xYFeEebNB6niASYtuO5XQIOZgAZvWccDMrgkESEl1cAo8e7tdu6TH2te1ITEXm/eF/uAKyQ3
\r
63 gOPh1puFVy/n3NyzJnnZ0fcf6wt0zW5GrP7SqdrT4L//+f/glCXPJCOC3i8yfJC/96VjY2JK
\r
64 xt+sOWd2njt7RU5Rg/PGEg1GtZtxMStidoQt8bb9UVFb0bDz2vfuR+vWOrPILWzw12r9wrdk
\r
65 gVbM64W/lFiKMxINtZiLihMBpsQZ9BcDAAA=
\r
66 Cc: notmuch@notmuchmail.org
\r
67 X-BeenThere: notmuch@notmuchmail.org
\r
68 X-Mailman-Version: 2.1.13
\r
70 List-Id: "Use and development of the notmuch mail system."
\r
71 <notmuch.notmuchmail.org>
\r
72 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
73 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
74 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
75 List-Post: <mailto:notmuch@notmuchmail.org>
\r
76 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
77 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
78 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
79 X-List-Received-Date: Wed, 11 Jan 2012 18:48:35 -0000
\r
81 Quoth Jani Nikula on Jan 11 at 10:11 am:
\r
82 > On Wed, 11 Jan 2012 00:02:52 -0500, Austin Clements <amdragon@MIT.EDU> wrote:
\r
83 > > This is useful for tags like "deleted" and "spam" that people
\r
84 > > generally want to exclude from query results. These exclusions will
\r
85 > > be overridden if a tag is explicitly mentioned in a query.
\r
87 > > lib/notmuch.h | 6 ++++++
\r
88 > > lib/query.cc | 33 +++++++++++++++++++++++++++++++++
\r
89 > > 2 files changed, 39 insertions(+), 0 deletions(-)
\r
91 > > diff --git a/lib/notmuch.h b/lib/notmuch.h
\r
92 > > index 9f23a10..0a3ae2b 100644
\r
93 > > --- a/lib/notmuch.h
\r
94 > > +++ b/lib/notmuch.h
\r
95 > > @@ -457,6 +457,12 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort);
\r
97 > > notmuch_query_get_sort (notmuch_query_t *query);
\r
99 > > +/* Add a tag that will be excluded by default from the query results.
\r
100 > > + * This exclusion will be overridden if this tag appears explicitly in
\r
101 > > + * the query. */
\r
103 > > +notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag);
\r
105 > > /* Execute a query for threads, returning a notmuch_threads_t object
\r
106 > > * which can be used to iterate over the results. The returned threads
\r
107 > > * object is owned by the query and as such, will only be valid until
\r
108 > > diff --git a/lib/query.cc b/lib/query.cc
\r
109 > > index b6c0f12..716db1c 100644
\r
110 > > --- a/lib/query.cc
\r
111 > > +++ b/lib/query.cc
\r
112 > > @@ -27,6 +27,7 @@ struct _notmuch_query {
\r
113 > > notmuch_database_t *notmuch;
\r
114 > > const char *query_string;
\r
115 > > notmuch_sort_t sort;
\r
116 > > + notmuch_string_list_t *exclude_terms;
\r
119 > > typedef struct _notmuch_mset_messages {
\r
120 > > @@ -76,6 +77,8 @@ notmuch_query_create (notmuch_database_t *notmuch,
\r
122 > > query->sort = NOTMUCH_SORT_NEWEST_FIRST;
\r
124 > > + query->exclude_terms = _notmuch_string_list_create (query);
\r
129 > > @@ -97,6 +100,13 @@ notmuch_query_get_sort (notmuch_query_t *query)
\r
130 > > return query->sort;
\r
134 > > +notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag)
\r
136 > > + char *term = talloc_asprintf (query, "%s%s", _find_prefix ("tag"), tag);
\r
137 > > + _notmuch_string_list_append (query->exclude_terms, term);
\r
140 > > /* We end up having to call the destructors explicitly because we had
\r
141 > > * to use "placement new" in order to initialize C++ objects within a
\r
142 > > * block that we allocated with talloc. So C++ is making talloc
\r
143 > > @@ -112,6 +122,25 @@ _notmuch_messages_destructor (notmuch_mset_messages_t *messages)
\r
148 > I'd like to have a comment here, or inline in the code, explaining the
\r
149 > following function a little bit.
\r
153 > > +static Xapian::Query
\r
154 > > +_notmuch_exclude_tags (notmuch_query_t *query, Xapian::Query xquery)
\r
156 > > + Xapian::TermIterator end = xquery.get_terms_end ();
\r
158 > > + for (notmuch_string_node_t *term = query->exclude_terms->head; term;
\r
159 > > + term = term->next) {
\r
160 > > + Xapian::TermIterator it = xquery.get_terms_begin ();
\r
161 > > + for (; it != end; it++) {
\r
162 > > + if (*it == term->string)
\r
164 > [This is a double reminder to me why I'm not that enthusiastic about
\r
165 > operator overloading in C++.]
\r
167 Actually, that's a good point. I had originally done this to prevent
\r
168 std::string from performing any internal allocation or copying (which
\r
169 calling c_str could do), but since it took me some digging to figure
\r
170 out if I had *actually* avoided this (turns out there's an overloaded
\r
171 string==char*, so I had), I've switched to using string.compare, which
\r
172 I think makes the behavior and performance more obvious.
\r
176 > > + if (it == end)
\r
177 > > + xquery = Xapian::Query (Xapian::Query::OP_AND_NOT,
\r
178 > > + xquery, Xapian::Query (term->string));
\r
180 > I briefly dug into Xapian documentation and source code, and became none
\r
181 > the wiser whether this copies the queries passed to it or not, i.e. does
\r
182 > this leak memory or not. I just presume you know what you're doing. ;)
\r
184 Since my code isn't doing any memory allocation, it can't leak memory.
\r
185 It could do a lot of copying, but it turns out that isn't a problem
\r
186 either because Xapian objects are internally reference-counted
\r
187 handles. So, in other words, if you write the obvious thing, it will
\r
188 do the right thing, which is totally contrary to what C++ has
\r
189 conditioned us to expect. ]:--8)
\r
191 > I think the function fails if someone is stupid enough to exclude the
\r
192 > same tag twice. I'm not sure if you should care. If you think so, you
\r
193 > could just check double add in notmuch_query_add_tag_exclude().
\r
195 It handles this correctly for two reasons. Suppose tag x is excluded
\r
196 twice. At worst, if tag:x doesn't appear in the query, the returned
\r
197 query will get two AND NOT tag:x's, but that doesn't affect the
\r
198 results. It turns out it doesn't even get doubled up for a slightly
\r
199 subtle reason: when the loop reaches the second x in the exclude list,
\r
200 it will iterate over the new query, which already has the AND NOT
\r
201 tag:x in it, so it will see the tag:x as if it were in the original
\r
202 query and not further modify the query.
\r
204 However, this did point out a bug. I was using the end iterator from
\r
205 the original query even when I started iterating over the modified
\r
208 I'll send out an updated series after someone looks at the third
\r
211 > Otherwise, looks good.
\r
214 > > + return xquery;
\r
217 > > notmuch_messages_t *
\r
218 > > notmuch_query_search_messages (notmuch_query_t *query)
\r
220 > > @@ -157,6 +186,8 @@ notmuch_query_search_messages (notmuch_query_t *query)
\r
221 > > mail_query, string_query);
\r
224 > > + final_query = _notmuch_exclude_tags (query, final_query);
\r
226 > > enquire.set_weighting_scheme (Xapian::BoolWeight());
\r
228 > > switch (query->sort) {
\r
229 > > @@ -436,6 +467,8 @@ notmuch_query_count_messages (notmuch_query_t *query)
\r
230 > > mail_query, string_query);
\r
233 > > + final_query = _notmuch_exclude_tags (query, final_query);
\r
235 > > enquire.set_weighting_scheme(Xapian::BoolWeight());
\r
236 > > enquire.set_docid_order(Xapian::Enquire::ASCENDING);
\r