query: update query subsys to use Message

This commit is contained in:
Dirk-Jan C. Binnema 2022-04-28 22:58:15 +03:00
parent 95710edff4
commit 459f6db476
4 changed files with 62 additions and 48 deletions

View File

@ -24,17 +24,17 @@ lib_mu=static_library(
[ [
'mu-bookmarks.cc', 'mu-bookmarks.cc',
'mu-contacts-cache.cc', 'mu-contacts-cache.cc',
'mu-maildir.cc',
'mu-parser.cc', 'mu-parser.cc',
'mu-query.cc',
'mu-query-match-deciders.cc', 'mu-query-match-deciders.cc',
'mu-query-threads.cc', 'mu-query-threads.cc',
'mu-query.cc',
'mu-runtime.cc', 'mu-runtime.cc',
'mu-script.cc', 'mu-script.cc',
'mu-server.cc', 'mu-server.cc',
'mu-store.cc', 'mu-store.cc',
'mu-tokenizer.cc', 'mu-tokenizer.cc',
'mu-xapian.cc', 'mu-xapian.cc'
'mu-maildir.cc'
], ],
dependencies: [ dependencies: [
glib_dep, glib_dep,

View File

@ -28,6 +28,7 @@
#include <limits> #include <limits>
#include <ostream> #include <ostream>
#include <cmath> #include <cmath>
#include <memory>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -303,9 +304,7 @@ public:
} }
/** /**
* get the corresponding Message for this iter; this instance is owned * get the corresponding Message for this iter
* by @this, and becomes invalid when iterating to the next, or @this is
* destroyed.; it's a 'floating' reference.
* *
* @return a Message or Nothing * @return a Message or Nothing
*/ */
@ -320,6 +319,19 @@ public:
Nothing); Nothing);
} }
/**
* get the corresponding Message for this iter a heap-allocated ptr;
*
* @return a unique ptr to a Message or P{}
*/
std::unique_ptr<Message> unique_message_ptr() const {
return xapian_try(
[&]()->std::unique_ptr<Message> {
return std::make_unique<Message>(Message(document()));
}, nullptr);
}
private: private:
Xapian::MSetIterator mset_it_; Xapian::MSetIterator mset_it_;
QueryMatches& query_matches_; QueryMatches& query_matches_;

View File

@ -29,10 +29,12 @@
#include <xapian.h> #include <xapian.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include "expected.hpp"
#include "mu-query-results.hh" #include "mu-query-results.hh"
#include "mu-query-match-deciders.hh" #include "mu-query-match-deciders.hh"
#include "mu-query-threads.hh" #include "mu-query-threads.hh"
#include <mu-xapian.hh> #include <mu-xapian.hh>
#include "utils/mu-xapian-utils.hh"
using namespace Mu; using namespace Mu;
@ -41,24 +43,23 @@ struct Query::Private {
// New // New
// bool calculate_threads (Xapian::Enquire& enq, size maxnum); // bool calculate_threads (Xapian::Enquire& enq, size maxnum);
Xapian::Enquire make_enquire(const std::string& expr, Xapian::Enquire make_enquire(const std::string& expr, Field::Id sortfield_id,
Option<Field::Id> sortfield_id, QueryFlags qflags) const;
QueryFlags qflags) const; Xapian::Enquire make_related_enquire(const StringSet& thread_ids,
Xapian::Enquire make_related_enquire(const StringSet& thread_ids, Field::Id sortfield_id,
Option<Field::Id> sortfield_id, QueryFlags qflags) const;
QueryFlags qflags) const;
Option<QueryResults> run_threaded(QueryResults&& qres, Xapian::Enquire& enq, Option<QueryResults> run_threaded(QueryResults&& qres, Xapian::Enquire& enq,
QueryFlags qflags, size_t max_size) const; QueryFlags qflags, size_t max_size) const;
Option<QueryResults> run_singular(const std::string& expr, Option<QueryResults> run_singular(const std::string& expr,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags, size_t maxnum) const; QueryFlags qflags, size_t maxnum) const;
Option<QueryResults> run_related(const std::string& expr, Option<QueryResults> run_related(const std::string& expr,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags, size_t maxnum) const; QueryFlags qflags, size_t maxnum) const;
Option<QueryResults> run(const std::string& expr, Option<QueryResults> run(const std::string& expr,
Option<Field::Id> sortfield_id, QueryFlags qflags, Field::Id sortfield_id, QueryFlags qflags,
size_t maxnum) const; size_t maxnum) const;
size_t store_size() const { return store_.database().get_doccount(); } 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 Xapian::Enquire
Query::Private::make_enquire(const std::string& expr, Query::Private::make_enquire(const std::string& expr,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags) const QueryFlags qflags) const
{ {
Xapian::Enquire enq{store_.database()}; 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()); 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; return enq;
} }
Xapian::Enquire Xapian::Enquire
Query::Private::make_related_enquire(const StringSet& thread_ids, Query::Private::make_related_enquire(const StringSet& thread_ids,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags) const QueryFlags qflags) const
{ {
Xapian::Enquire enq{store_.database()}; 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()}; Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()};
enq.set_query(qr); enq.set_query(qr);
if (sortfield_id) sort_enquire(enq, sortfield_id, qflags);
sort_enquire(enq, *sortfield_id, qflags);
return enq; return enq;
} }
@ -156,7 +155,7 @@ Query::Private::run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFla
Option<QueryResults> Option<QueryResults>
Query::Private::run_singular(const std::string& expr, Query::Private::run_singular(const std::string& expr,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags, size_t maxnum) const QueryFlags qflags, size_t maxnum) const
{ {
// i.e. a query _without_ related messages, but still possibly // 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<QueryResults> Option<QueryResults>
Query::Private::run_related(const std::string& expr, Query::Private::run_related(const std::string& expr,
Option<Field::Id> sortfield_id, Field::Id sortfield_id,
QueryFlags qflags, size_t maxnum) const QueryFlags qflags, size_t maxnum) const
{ {
// i.e. a query _with_ related messages and possibly with threading. // 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. // is unlimited and the sorting happens during threading.
auto r_enq = std::invoke([&]{ auto r_enq = std::invoke([&]{
if (threading) if (threading)
return make_related_enquire(minfo.thread_ids, Nothing, qflags); return make_related_enquire(minfo.thread_ids, Field::Id::Date,
qflags );
else else
return make_related_enquire(minfo.thread_ids, sortfield_id, qflags); return make_related_enquire(minfo.thread_ids, sortfield_id, qflags);
}); });
@ -243,37 +243,38 @@ Query::Private::run_related(const std::string& expr,
} }
Option<QueryResults> Option<QueryResults>
Query::Private::run(const std::string& expr, Query::Private::run(const std::string& expr, Field::Id sortfield_id, QueryFlags qflags,
Option<Field::Id> sortfield_id, QueryFlags qflags,
size_t maxnum) const size_t maxnum) const
{ {
const auto eff_maxnum{maxnum == 0 ? store_size() : maxnum}; 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)) 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 else
return run_singular(expr, eff_sortfield, qflags, eff_maxnum); return run_singular(expr, sortfield_id, qflags, eff_maxnum);
} }
Option<QueryResults> Result<QueryResults>
Query::run(const std::string& expr, Option<Field::Id> sortfield_id, Query::run(const std::string& expr, Field::Id sortfield_id,
QueryFlags qflags, size_t maxnum) const QueryFlags qflags, size_t maxnum) const
try { {
// some flags are for internal use only. // 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( StopWatch sw{format(
"ran query '%s'; related: %s; threads: %s; max-size: %zu", expr.c_str(), "ran query '%s'; related: %s; threads: %s; max-size: %zu", expr.c_str(),
any_of(qflags & QueryFlags::IncludeRelated) ? "yes" : "no", any_of(qflags & QueryFlags::IncludeRelated) ? "yes" : "no",
any_of(qflags & QueryFlags::Threading) ? "yes" : "no", maxnum)}; 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<QueryResults>(Ok(std::move(res.value())));
else
return Result<QueryResults>(Err(Error::Code::Query,
"failed to run query"));
});
} catch (...) {
return Nothing;
} }
size_t size_t
@ -290,7 +291,8 @@ Query::count(const std::string& expr) const
} }
std::string std::string
Query::parse(const std::string& expr, bool xapian) const Query::parse(const std::
string& expr, bool xapian) const
{ {
WarningVec warns; WarningVec warns;
const auto tree{priv_->parser_.parse(expr, warns)}; const auto tree{priv_->parser_.parse(expr, warns)};

View File

@ -27,6 +27,7 @@
#include <mu-query-results.hh> #include <mu-query-results.hh>
#include <utils/mu-utils.hh> #include <utils/mu-utils.hh>
#include <utils/mu-option.hh> #include <utils/mu-option.hh>
#include <utils/mu-result.hh>
#include <message/mu-message.hh> #include <message/mu-message.hh>
namespace Mu { namespace Mu {
@ -37,15 +38,14 @@ public:
* Run a query on the store * Run a query on the store
* *
* @param expr the search expression * @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 flags query flags
* @param maxnum maximum number of results to return. 0 for 'no limit' * @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
*/ */
Result<QueryResults> run(const std::string& expr,
Option<QueryResults> run(const std::string& expr = "", Field::Id sortfield_id = Field::Id::Date,
Option<Field::Id> sortfield_id = {},
QueryFlags flags = QueryFlags::None, QueryFlags flags = QueryFlags::None,
size_t maxnum = 0) const; size_t maxnum = 0) const;