X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=lib%2Fquery.cc;h=59f4011b31d3a3f5616227d352b8f7234b05ee0f;hp=7d191e529ec72974a2ec5adad21fe63e87e2942f;hb=f6cb896bc4c0bafca1acd5ac3fb45169cd893e29;hpb=94eb9aacd40a8aa133f64bbe5ed71c0138fb5ed9 diff --git a/lib/query.cc b/lib/query.cc index 7d191e52..59f4011b 100644 --- a/lib/query.cc +++ b/lib/query.cc @@ -31,11 +31,12 @@ struct _notmuch_query { notmuch_sort_t sort; }; -struct _notmuch_messages { +typedef struct _notmuch_mset_messages { + notmuch_messages_t base; notmuch_database_t *notmuch; Xapian::MSetIterator iterator; Xapian::MSetIterator iterator_end; -}; +} notmuch_mset_messages_t; struct _notmuch_threads { notmuch_query_t *query; @@ -75,19 +76,42 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort) query->sort = sort; } +/* We end up having to call the destructors explicitly because we had + * to use "placement new" in order to initialize C++ objects within a + * block that we allocated with talloc. So C++ is making talloc + * slightly less simple to use, (we wouldn't need + * talloc_set_destructor at all otherwise). + */ +static int +_notmuch_messages_destructor (notmuch_mset_messages_t *messages) +{ + messages->iterator.~MSetIterator (); + messages->iterator_end.~MSetIterator (); + + return 0; +} + notmuch_messages_t * notmuch_query_search_messages (notmuch_query_t *query) { notmuch_database_t *notmuch = query->notmuch; const char *query_string = query->query_string; - notmuch_message_list_t *message_list; - Xapian::MSetIterator i; + notmuch_mset_messages_t *messages; - message_list = _notmuch_message_list_create (query); - if (unlikely (message_list == NULL)) + messages = talloc (query, notmuch_mset_messages_t); + if (unlikely (messages == NULL)) return NULL; try { + + messages->base.is_of_list_type = FALSE; + messages->base.iterator = NULL; + messages->notmuch = notmuch; + new (&messages->iterator) Xapian::MSetIterator (); + new (&messages->iterator_end) Xapian::MSetIterator (); + + talloc_set_destructor (messages, _notmuch_messages_destructor); + Xapian::Enquire enquire (*notmuch->xapian_db); Xapian::Query mail_query (talloc_asprintf (query, "%s%s", _find_prefix ("type"), @@ -101,7 +125,9 @@ notmuch_query_search_messages (notmuch_query_t *query) Xapian::QueryParser::FLAG_WILDCARD | Xapian::QueryParser::FLAG_PURE_NOT); - if (strcmp (query_string, "") == 0) { + if (strcmp (query_string, "") == 0 || + strcmp (query_string, "*") == 0) + { final_query = mail_query; } else { string_query = notmuch->query_parser-> @@ -110,6 +136,8 @@ notmuch_query_search_messages (notmuch_query_t *query) mail_query, string_query); } + enquire.set_weighting_scheme (Xapian::BoolWeight()); + switch (query->sort) { case NOTMUCH_SORT_OLDEST_FIRST: enquire.set_sort_by_value (NOTMUCH_VALUE_TIMESTAMP, FALSE); @@ -120,6 +148,8 @@ notmuch_query_search_messages (notmuch_query_t *query) case NOTMUCH_SORT_MESSAGE_ID: enquire.set_sort_by_value (NOTMUCH_VALUE_MESSAGE_ID, FALSE); break; + case NOTMUCH_SORT_UNSORTED: + break; } #if DEBUG_QUERY @@ -130,31 +160,67 @@ notmuch_query_search_messages (notmuch_query_t *query) mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ()); - for (i = mset.begin (); i != mset.end (); i++) { - notmuch_message_t *message; - notmuch_private_status_t status; - - message = _notmuch_message_create (message_list, notmuch, - *i, &status); - if (message == NULL) - { - if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) - INTERNAL_ERROR ("A message iterator contains a " - "non-existent document ID.\n"); - break; - } - - _notmuch_message_list_add_message (message_list, message); - } + messages->iterator = mset.begin (); + messages->iterator_end = mset.end (); + + return &messages->base; } catch (const Xapian::Error &error) { fprintf (stderr, "A Xapian exception occurred performing query: %s\n", error.get_msg().c_str()); fprintf (stderr, "Query string was: %s\n", query->query_string); notmuch->exception_reported = TRUE; + talloc_free (messages); + return NULL; } +} + +notmuch_bool_t +_notmuch_mset_messages_valid (notmuch_messages_t *messages) +{ + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; - return _notmuch_messages_create (message_list); + return (mset_messages->iterator != mset_messages->iterator_end); +} + +notmuch_message_t * +_notmuch_mset_messages_get (notmuch_messages_t *messages) +{ + notmuch_message_t *message; + Xapian::docid doc_id; + notmuch_private_status_t status; + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; + + if (! _notmuch_mset_messages_valid (&mset_messages->base)) + return NULL; + + doc_id = *mset_messages->iterator; + + message = _notmuch_message_create (mset_messages, + mset_messages->notmuch, doc_id, + &status); + + if (message == NULL && + status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) + { + INTERNAL_ERROR ("a messages iterator contains a non-existent document ID.\n"); + } + + return message; +} + +void +_notmuch_mset_messages_move_to_next (notmuch_messages_t *messages) +{ + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; + + mset_messages->iterator++; } /* Glib objects force use to use a talloc destructor as well, (but not @@ -183,6 +249,10 @@ notmuch_query_search_threads (notmuch_query_t *query) free, NULL); threads->messages = notmuch_query_search_messages (query); + if (threads->messages == NULL) { + talloc_free (threads); + return NULL; + } threads->thread_id = NULL; @@ -198,14 +268,14 @@ notmuch_query_destroy (notmuch_query_t *query) } notmuch_bool_t -notmuch_threads_has_more (notmuch_threads_t *threads) +notmuch_threads_valid (notmuch_threads_t *threads) { notmuch_message_t *message; if (threads->thread_id) return TRUE; - while (notmuch_messages_has_more (threads->messages)) + while (notmuch_messages_valid (threads->messages)) { message = notmuch_messages_get (threads->messages); @@ -217,11 +287,11 @@ notmuch_threads_has_more (notmuch_threads_t *threads) { g_hash_table_insert (threads->threads, xstrdup (threads->thread_id), NULL); - notmuch_messages_advance (threads->messages); + notmuch_messages_move_to_next (threads->messages); return TRUE; } - notmuch_messages_advance (threads->messages); + notmuch_messages_move_to_next (threads->messages); } threads->thread_id = NULL; @@ -231,17 +301,18 @@ notmuch_threads_has_more (notmuch_threads_t *threads) notmuch_thread_t * notmuch_threads_get (notmuch_threads_t *threads) { - if (! notmuch_threads_has_more (threads)) + if (! notmuch_threads_valid (threads)) return NULL; return _notmuch_thread_create (threads->query, threads->query->notmuch, threads->thread_id, - threads->query->query_string); + threads->query->query_string, + threads->query->sort); } void -notmuch_threads_advance (notmuch_threads_t *threads) +notmuch_threads_move_to_next (notmuch_threads_t *threads) { threads->thread_id = NULL; } @@ -257,7 +328,7 @@ notmuch_query_count_messages (notmuch_query_t *query) { notmuch_database_t *notmuch = query->notmuch; const char *query_string = query->query_string; - Xapian::doccount count; + Xapian::doccount count = 0; try { Xapian::Enquire enquire (*notmuch->xapian_db); @@ -273,7 +344,9 @@ notmuch_query_count_messages (notmuch_query_t *query) Xapian::QueryParser::FLAG_WILDCARD | Xapian::QueryParser::FLAG_PURE_NOT); - if (strcmp (query_string, "") == 0) { + if (strcmp (query_string, "") == 0 || + strcmp (query_string, "*") == 0) + { final_query = mail_query; } else { string_query = notmuch->query_parser->