diff --git a/lib/meson.build b/lib/meson.build index 469980e8..00920195 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -24,17 +24,17 @@ lib_mu=static_library( [ 'mu-bookmarks.cc', 'mu-contacts-cache.cc', + 'mu-maildir.cc', 'mu-parser.cc', - 'mu-query.cc', 'mu-query-match-deciders.cc', 'mu-query-threads.cc', + 'mu-query.cc', 'mu-runtime.cc', 'mu-script.cc', 'mu-server.cc', 'mu-store.cc', 'mu-tokenizer.cc', - 'mu-xapian.cc', - 'mu-maildir.cc' + 'mu-xapian.cc' ], dependencies: [ glib_dep, diff --git a/lib/mu-query-results.hh b/lib/mu-query-results.hh index ad721cb6..9c0bbbc1 100644 --- a/lib/mu-query-results.hh +++ b/lib/mu-query-results.hh @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -303,9 +304,7 @@ public: } /** - * get the corresponding Message for this iter; this instance is owned - * by @this, and becomes invalid when iterating to the next, or @this is - * destroyed.; it's a 'floating' reference. + * get the corresponding Message for this iter * * @return a Message or Nothing */ @@ -320,6 +319,19 @@ public: Nothing); } + /** + * get the corresponding Message for this iter a heap-allocated ptr; + * + * @return a unique ptr to a Message or P{} + */ + std::unique_ptr unique_message_ptr() const { + return xapian_try( + [&]()->std::unique_ptr { + return std::make_unique(Message(document())); + }, nullptr); + } + + private: Xapian::MSetIterator mset_it_; QueryMatches& query_matches_; diff --git a/lib/mu-query.cc b/lib/mu-query.cc index a6218c01..b5821f83 100644 --- a/lib/mu-query.cc +++ b/lib/mu-query.cc @@ -29,10 +29,12 @@ #include #include +#include "expected.hpp" #include "mu-query-results.hh" #include "mu-query-match-deciders.hh" #include "mu-query-threads.hh" #include +#include "utils/mu-xapian-utils.hh" using namespace Mu; @@ -41,24 +43,23 @@ struct Query::Private { // New // bool calculate_threads (Xapian::Enquire& enq, size maxnum); - Xapian::Enquire make_enquire(const std::string& expr, - Option sortfield_id, - QueryFlags qflags) const; - Xapian::Enquire make_related_enquire(const StringSet& thread_ids, - Option sortfield_id, - QueryFlags qflags) const; + Xapian::Enquire make_enquire(const std::string& expr, Field::Id sortfield_id, + QueryFlags qflags) const; + Xapian::Enquire make_related_enquire(const StringSet& thread_ids, + Field::Id sortfield_id, + QueryFlags qflags) const; Option run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFlags qflags, size_t max_size) const; Option run_singular(const std::string& expr, - Option sortfield_id, + Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const; Option run_related(const std::string& expr, - Option sortfield_id, + Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const; - Option run(const std::string& expr, - Option sortfield_id, QueryFlags qflags, + Option run(const std::string& expr, + Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const; size_t store_size() const { return store_.database().get_doccount(); } @@ -83,9 +84,9 @@ sort_enquire(Xapian::Enquire& enq, Field::Id sortfield_id, QueryFlags qflags) } Xapian::Enquire -Query::Private::make_enquire(const std::string& expr, - Option sortfield_id, - QueryFlags qflags) const +Query::Private::make_enquire(const std::string& expr, + Field::Id sortfield_id, + QueryFlags qflags) const { Xapian::Enquire enq{store_.database()}; @@ -100,15 +101,14 @@ Query::Private::make_enquire(const std::string& expr, g_debug("qtree: %s", to_string(tree).c_str()); } - if (sortfield_id) - sort_enquire(enq, *sortfield_id, qflags); + sort_enquire(enq, sortfield_id, qflags); return enq; } Xapian::Enquire Query::Private::make_related_enquire(const StringSet& thread_ids, - Option sortfield_id, + Field::Id sortfield_id, QueryFlags qflags) const { Xapian::Enquire enq{store_.database()}; @@ -119,8 +119,7 @@ Query::Private::make_related_enquire(const StringSet& thread_ids, Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()}; enq.set_query(qr); - if (sortfield_id) - sort_enquire(enq, *sortfield_id, qflags); + sort_enquire(enq, sortfield_id, qflags); return enq; } @@ -156,7 +155,7 @@ Query::Private::run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFla Option Query::Private::run_singular(const std::string& expr, - Option sortfield_id, + Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const { // i.e. a query _without_ related messages, but still possibly @@ -197,7 +196,7 @@ opt_string(const Xapian::Document& doc, Field::Id id) noexcept Option Query::Private::run_related(const std::string& expr, - Option sortfield_id, + Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const { // i.e. a query _with_ related messages and possibly with threading. @@ -231,7 +230,8 @@ Query::Private::run_related(const std::string& expr, // is unlimited and the sorting happens during threading. auto r_enq = std::invoke([&]{ if (threading) - return make_related_enquire(minfo.thread_ids, Nothing, qflags); + return make_related_enquire(minfo.thread_ids, Field::Id::Date, + qflags ); else return make_related_enquire(minfo.thread_ids, sortfield_id, qflags); }); @@ -243,37 +243,38 @@ Query::Private::run_related(const std::string& expr, } Option -Query::Private::run(const std::string& expr, - Option sortfield_id, QueryFlags qflags, +Query::Private::run(const std::string& expr, Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const { const auto eff_maxnum{maxnum == 0 ? store_size() : maxnum}; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wextra" - const auto eff_sortfield{sortfield_id.value_or(Field::Id::Date)}; -#pragma GCC diagnostic pop + if (any_of(qflags & QueryFlags::IncludeRelated)) - return run_related(expr, eff_sortfield, qflags, eff_maxnum); + return run_related(expr, sortfield_id, qflags, eff_maxnum); else - return run_singular(expr, eff_sortfield, qflags, eff_maxnum); + return run_singular(expr, sortfield_id, qflags, eff_maxnum); } -Option -Query::run(const std::string& expr, Option sortfield_id, +Result +Query::run(const std::string& expr, Field::Id sortfield_id, QueryFlags qflags, size_t maxnum) const -try { +{ // some flags are for internal use only. - g_return_val_if_fail(none_of(qflags & QueryFlags::Leader), Nothing); + g_return_val_if_fail(none_of(qflags & QueryFlags::Leader), + Err(Error::Code::InvalidArgument, "cannot pass Leader flag")); StopWatch sw{format( "ran query '%s'; related: %s; threads: %s; max-size: %zu", expr.c_str(), any_of(qflags & QueryFlags::IncludeRelated) ? "yes" : "no", any_of(qflags & QueryFlags::Threading) ? "yes" : "no", maxnum)}; - return priv_->run(expr, sortfield_id, qflags, maxnum); + return xapian_try_result([&]{ + if (auto&& res = priv_->run(expr, sortfield_id, qflags, maxnum); res) + return Result(Ok(std::move(res.value()))); + else + return Result(Err(Error::Code::Query, + "failed to run query")); + }); -} catch (...) { - return Nothing; } size_t @@ -290,7 +291,8 @@ Query::count(const std::string& expr) const } std::string -Query::parse(const std::string& expr, bool xapian) const +Query::parse(const std:: + string& expr, bool xapian) const { WarningVec warns; const auto tree{priv_->parser_.parse(expr, warns)}; diff --git a/lib/mu-query.hh b/lib/mu-query.hh index 92653969..ad042e1b 100644 --- a/lib/mu-query.hh +++ b/lib/mu-query.hh @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace Mu { @@ -37,15 +38,14 @@ public: * Run a query on the store * * @param expr the search expression - * @param sortfieldid the sortfield-id. If the field is NONE, sort by DATE + * @param sortfield_id the sortfield-id. Default to Date * @param flags query flags * @param maxnum maximum number of results to return. 0 for 'no limit' * - * @return the query-results, or Nothing in case of error. + * @return the query-results or an error */ - - Option run(const std::string& expr = "", - Option sortfield_id = {}, + Result run(const std::string& expr, + Field::Id sortfield_id = Field::Id::Date, QueryFlags flags = QueryFlags::None, size_t maxnum = 0) const;