+
+unsigned int
+notmuch_query_count_messages (notmuch_query_t *query)
+{
+ notmuch_status_t status;
+ unsigned int count;
+
+ status = notmuch_query_count_messages_st (query, &count);
+ return status ? 0 : count;
+}
+
+notmuch_status_t
+notmuch_query_count_messages_st (notmuch_query_t *query, unsigned *count_out)
+{
+ return _notmuch_query_count_documents (query, "mail", count_out);
+}
+
+notmuch_status_t
+_notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsigned *count_out)
+{
+ notmuch_database_t *notmuch = query->notmuch;
+ const char *query_string = query->query_string;
+ Xapian::doccount count = 0;
+
+ try {
+ Xapian::Enquire enquire (*notmuch->xapian_db);
+ Xapian::Query mail_query (talloc_asprintf (query, "%s%s",
+ _find_prefix ("type"),
+ type));
+ Xapian::Query string_query, final_query, exclude_query;
+ Xapian::MSet mset;
+
+ if (strcmp (query_string, "") == 0 ||
+ strcmp (query_string, "*") == 0)
+ {
+ final_query = mail_query;
+ } else {
+ string_query = notmuch->query_parser->
+ parse_query (query_string, NOTMUCH_QUERY_PARSER_FLAGS);
+ final_query = Xapian::Query (Xapian::Query::OP_AND,
+ mail_query, string_query);
+ }
+
+ exclude_query = _notmuch_exclude_tags (query, final_query);
+
+ final_query = Xapian::Query (Xapian::Query::OP_AND_NOT,
+ final_query, exclude_query);
+
+ enquire.set_weighting_scheme(Xapian::BoolWeight());
+ enquire.set_docid_order(Xapian::Enquire::ASCENDING);
+
+ if (_debug_query ()) {
+ fprintf (stderr, "Exclude query is:\n%s\n",
+ exclude_query.get_description ().c_str ());
+ fprintf (stderr, "Final query is:\n%s\n",
+ final_query.get_description ().c_str ());
+ }
+
+ enquire.set_query (final_query);
+
+ /*
+ * Set the checkatleast parameter to the number of documents
+ * in the database to make get_matches_estimated() exact.
+ */
+ mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount (),
+ notmuch->xapian_db->get_doccount ());
+
+ count = mset.get_matches_estimated();
+
+ } catch (const Xapian::Error &error) {
+ _notmuch_database_log (notmuch,
+ "A Xapian exception occurred performing query: %s\n"
+ "Query string was: %s\n",
+ error.get_msg().c_str(),
+ query->query_string);
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+ *count_out = count;
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
+unsigned
+notmuch_query_count_threads (notmuch_query_t *query)
+{
+ notmuch_status_t status;
+ unsigned int count;
+
+ status = notmuch_query_count_threads_st (query, &count);
+ return status ? 0 : count;
+}
+
+notmuch_status_t
+notmuch_query_count_threads_st (notmuch_query_t *query, unsigned *count)
+{
+ notmuch_messages_t *messages;
+ GHashTable *hash;
+ notmuch_sort_t sort;
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
+
+ sort = query->sort;
+ query->sort = NOTMUCH_SORT_UNSORTED;
+ ret = notmuch_query_search_messages_st (query, &messages);
+ if (ret)
+ return ret;
+ query->sort = sort;
+ if (messages == NULL)
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+ if (hash == NULL) {
+ talloc_free (messages);
+ return NOTMUCH_STATUS_OUT_OF_MEMORY;
+ }
+
+ while (notmuch_messages_valid (messages)) {
+ notmuch_message_t *message = notmuch_messages_get (messages);
+ const char *thread_id = notmuch_message_get_thread_id (message);
+ char *thread_id_copy = talloc_strdup (messages, thread_id);
+ if (unlikely (thread_id_copy == NULL)) {
+ notmuch_message_destroy (message);
+ ret = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+ }
+ g_hash_table_insert (hash, thread_id_copy, NULL);
+ notmuch_message_destroy (message);
+ notmuch_messages_move_to_next (messages);
+ }
+
+ *count = g_hash_table_size (hash);
+
+ DONE:
+ g_hash_table_unref (hash);
+ talloc_free (messages);
+
+ return ret;
+}
+
+notmuch_database_t *
+notmuch_query_get_database (const notmuch_query_t *query)
+{
+ return query->notmuch;
+}