clang-format: update c/cc coding style
Update all cc code using .clang-format; please do so as well for future PRs etc.; emacs has a handy 'clang-format' mode to make this automatic. For comparing old changes with git blame, we can disregard this one using --ignore-rev (see https://www.moxio.com/blog/43/ignoring-bulk-change-commits-with-git-blame )
This commit is contained in:
346
lib/mu-query.cc
346
lib/mu-query.cc
@ -38,145 +38,149 @@
|
||||
using namespace Mu;
|
||||
|
||||
struct Query::Private {
|
||||
Private(const Store& store): store_{store},
|
||||
parser_{store_} {}
|
||||
// New
|
||||
//bool calculate_threads (Xapian::Enquire& enq, size maxnum);
|
||||
Private(const Store& store) : store_{store}, parser_{store_} {}
|
||||
// New
|
||||
// bool calculate_threads (Xapian::Enquire& enq, size maxnum);
|
||||
|
||||
Xapian::Enquire make_enquire (const std::string& expr,
|
||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
||||
Xapian::Enquire make_related_enquire (const StringSet& thread_ids,
|
||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
||||
Xapian::Enquire
|
||||
make_enquire(const std::string& expr, MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
||||
Xapian::Enquire make_related_enquire(const StringSet& thread_ids,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags) const;
|
||||
|
||||
Option<QueryResults> run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
||||
QueryFlags qflags) const;
|
||||
Option<QueryResults> run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const;
|
||||
Option<QueryResults> run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const;
|
||||
Option<QueryResults> run (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const;
|
||||
Option<QueryResults>
|
||||
run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFlags qflags) const;
|
||||
Option<QueryResults> run_singular(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
size_t maxnum) const;
|
||||
Option<QueryResults> run_related(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
size_t maxnum) const;
|
||||
Option<QueryResults> run(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
size_t maxnum) const;
|
||||
|
||||
const Store& store_;
|
||||
const Parser parser_;
|
||||
const Store& store_;
|
||||
const Parser parser_;
|
||||
};
|
||||
|
||||
Query::Query(const Store& store):
|
||||
priv_{std::make_unique<Private>(store)}
|
||||
{}
|
||||
Query::Query(const Store& store) : priv_{std::make_unique<Private>(store)} {}
|
||||
|
||||
Query::Query(Query&& other) = default;
|
||||
|
||||
Query::~Query() = default;
|
||||
|
||||
|
||||
static Xapian::Enquire&
|
||||
maybe_sort (Xapian::Enquire& enq, MuMsgFieldId sortfieldid, QueryFlags qflags)
|
||||
maybe_sort(Xapian::Enquire& enq, MuMsgFieldId sortfieldid, QueryFlags qflags)
|
||||
{
|
||||
if (sortfieldid != MU_MSG_FIELD_ID_NONE)
|
||||
enq.set_sort_by_value(static_cast<Xapian::valueno>(sortfieldid),
|
||||
any_of(qflags & QueryFlags::Descending));
|
||||
return enq;
|
||||
if (sortfieldid != MU_MSG_FIELD_ID_NONE)
|
||||
enq.set_sort_by_value(static_cast<Xapian::valueno>(sortfieldid),
|
||||
any_of(qflags & QueryFlags::Descending));
|
||||
return enq;
|
||||
}
|
||||
|
||||
Xapian::Enquire
|
||||
Query::Private::make_enquire (const std::string& expr,
|
||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const
|
||||
Query::Private::make_enquire(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags) const
|
||||
{
|
||||
Xapian::Enquire enq{store_.database()};
|
||||
Xapian::Enquire enq{store_.database()};
|
||||
|
||||
if (expr.empty() || expr == R"("")")
|
||||
enq.set_query(Xapian::Query::MatchAll);
|
||||
else {
|
||||
WarningVec warns;
|
||||
const auto tree{parser_.parse(expr, warns)};
|
||||
for (auto&& w: warns)
|
||||
g_warning ("query warning: %s", to_string(w).c_str());
|
||||
enq.set_query(xapian_query(tree));
|
||||
g_debug ("qtree: %s", to_string(tree).c_str());
|
||||
}
|
||||
if (expr.empty() || expr == R"("")")
|
||||
enq.set_query(Xapian::Query::MatchAll);
|
||||
else {
|
||||
WarningVec warns;
|
||||
const auto tree{parser_.parse(expr, warns)};
|
||||
for (auto&& w : warns)
|
||||
g_warning("query warning: %s", to_string(w).c_str());
|
||||
enq.set_query(xapian_query(tree));
|
||||
g_debug("qtree: %s", to_string(tree).c_str());
|
||||
}
|
||||
|
||||
return maybe_sort (enq, sortfieldid, qflags);
|
||||
return maybe_sort(enq, sortfieldid, qflags);
|
||||
}
|
||||
|
||||
Xapian::Enquire
|
||||
Query::Private::make_related_enquire (const StringSet& thread_ids,
|
||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const
|
||||
Query::Private::make_related_enquire(const StringSet& thread_ids,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags) const
|
||||
{
|
||||
Xapian::Enquire enq{store_.database()};
|
||||
static std::string pfx (1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID));
|
||||
Xapian::Enquire enq{store_.database()};
|
||||
static std::string pfx(1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID));
|
||||
|
||||
std::vector<Xapian::Query> qvec;
|
||||
for (auto&& t: thread_ids)
|
||||
qvec.emplace_back(pfx + t);
|
||||
Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()};
|
||||
enq.set_query(qr);
|
||||
|
||||
return maybe_sort (enq, sortfieldid, qflags);
|
||||
std::vector<Xapian::Query> qvec;
|
||||
for (auto&& t : thread_ids)
|
||||
qvec.emplace_back(pfx + t);
|
||||
Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()};
|
||||
enq.set_query(qr);
|
||||
|
||||
return maybe_sort(enq, sortfieldid, qflags);
|
||||
}
|
||||
|
||||
struct ThreadKeyMaker: public Xapian::KeyMaker {
|
||||
ThreadKeyMaker (const QueryMatches& matches): match_info_(matches) {}
|
||||
std::string operator()(const Xapian::Document& doc) const override {
|
||||
const auto it{match_info_.find(doc.get_docid())};
|
||||
return (it == match_info_.end()) ? "" : it->second.thread_path;
|
||||
}
|
||||
const QueryMatches& match_info_;
|
||||
struct ThreadKeyMaker : public Xapian::KeyMaker {
|
||||
ThreadKeyMaker(const QueryMatches& matches) : match_info_(matches) {}
|
||||
std::string operator()(const Xapian::Document& doc) const override
|
||||
{
|
||||
const auto it{match_info_.find(doc.get_docid())};
|
||||
return (it == match_info_.end()) ? "" : it->second.thread_path;
|
||||
}
|
||||
const QueryMatches& match_info_;
|
||||
};
|
||||
|
||||
Option<QueryResults>
|
||||
Query::Private::run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
||||
QueryFlags qflags) const
|
||||
Query::Private::run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFlags qflags) const
|
||||
{
|
||||
const auto descending{any_of(qflags & QueryFlags::Descending)};
|
||||
const auto descending{any_of(qflags & QueryFlags::Descending)};
|
||||
|
||||
calculate_threads(qres, descending);
|
||||
calculate_threads(qres, descending);
|
||||
|
||||
ThreadKeyMaker key_maker{qres.query_matches()};
|
||||
enq.set_sort_by_key(&key_maker, descending);
|
||||
ThreadKeyMaker key_maker{qres.query_matches()};
|
||||
enq.set_sort_by_key(&key_maker, descending);
|
||||
|
||||
DeciderInfo minfo;
|
||||
minfo.matches = qres.query_matches();
|
||||
auto mset{enq.get_mset(0, store_.size(), {},
|
||||
make_thread_decider(qflags, minfo).get())};
|
||||
mset.fetch();
|
||||
DeciderInfo minfo;
|
||||
minfo.matches = qres.query_matches();
|
||||
auto mset{enq.get_mset(0, store_.size(), {}, make_thread_decider(qflags, minfo).get())};
|
||||
mset.fetch();
|
||||
|
||||
return QueryResults{mset, std::move(qres.query_matches())};
|
||||
return QueryResults{mset, std::move(qres.query_matches())};
|
||||
}
|
||||
|
||||
|
||||
Option<QueryResults>
|
||||
Query::Private::run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const
|
||||
Query::Private::run_singular(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
size_t maxnum) const
|
||||
{
|
||||
// i.e. a query _without_ related messages, but still possibly
|
||||
// with threading.
|
||||
//
|
||||
// In the threading case, the sortfield-id is ignored, we always sort by
|
||||
// date (since threading the threading results are always by date.)
|
||||
// i.e. a query _without_ related messages, but still possibly
|
||||
// with threading.
|
||||
//
|
||||
// In the threading case, the sortfield-id is ignored, we always sort by
|
||||
// date (since threading the threading results are always by date.)
|
||||
|
||||
const auto singular_qflags{qflags | QueryFlags::Leader};
|
||||
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
||||
const auto singular_qflags{qflags | QueryFlags::Leader};
|
||||
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
||||
|
||||
DeciderInfo minfo{};
|
||||
DeciderInfo minfo{};
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
auto enq{make_enquire(expr, threading ? MU_MSG_FIELD_ID_DATE : sortfieldid, qflags)};
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
auto enq{make_enquire(expr, threading ? MU_MSG_FIELD_ID_DATE : sortfieldid, qflags)};
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
#pragma GCC diagnostic pop
|
||||
auto mset{enq.get_mset(0, maxnum, {}, make_leader_decider(singular_qflags, minfo).get())};
|
||||
mset.fetch();
|
||||
auto mset{enq.get_mset(0, maxnum, {}, make_leader_decider(singular_qflags, minfo).get())};
|
||||
mset.fetch();
|
||||
|
||||
auto qres{QueryResults{mset, std::move(minfo.matches)}};
|
||||
auto qres{QueryResults{mset, std::move(minfo.matches)}};
|
||||
|
||||
return threading ? run_threaded(std::move(qres), enq, qflags) : qres;
|
||||
return threading ? run_threaded(std::move(qres), enq, qflags) : qres;
|
||||
}
|
||||
|
||||
static Option<std::string>
|
||||
opt_string (const Xapian::Document &doc, MuMsgFieldId id) noexcept
|
||||
opt_string(const Xapian::Document& doc, MuMsgFieldId id) noexcept
|
||||
{
|
||||
std::string val = xapian_try([&]{ return doc.get_value (id);}, std::string{""});
|
||||
std::string val = xapian_try([&] { return doc.get_value(id); }, std::string{""});
|
||||
if (val.empty())
|
||||
return Nothing;
|
||||
else
|
||||
@ -184,107 +188,113 @@ opt_string (const Xapian::Document &doc, MuMsgFieldId id) noexcept
|
||||
}
|
||||
|
||||
Option<QueryResults>
|
||||
Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const
|
||||
Query::Private::run_related(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
size_t maxnum) const
|
||||
{
|
||||
// i.e. a query _with_ related messages and possibly with threading.
|
||||
//
|
||||
// In the threading case, the sortfield-id is ignored, we always sort by
|
||||
// date (since threading the threading results are always by date.);
|
||||
// moreover, in either threaded or non-threaded case, we sort the first
|
||||
// ("leader") query by date, i.e, we prefer the newest or oldest
|
||||
// (descending) messages.
|
||||
const auto leader_qflags{QueryFlags::Leader | qflags};
|
||||
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
||||
// i.e. a query _with_ related messages and possibly with threading.
|
||||
//
|
||||
// In the threading case, the sortfield-id is ignored, we always sort by
|
||||
// date (since threading the threading results are always by date.);
|
||||
// moreover, in either threaded or non-threaded case, we sort the first
|
||||
// ("leader") query by date, i.e, we prefer the newest or oldest
|
||||
// (descending) messages.
|
||||
const auto leader_qflags{QueryFlags::Leader | qflags};
|
||||
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
||||
|
||||
// Run our first, "leader" query
|
||||
DeciderInfo minfo{};
|
||||
auto enq{make_enquire(expr, MU_MSG_FIELD_ID_DATE, leader_qflags)};
|
||||
const auto mset{enq.get_mset(0, maxnum, {},
|
||||
make_leader_decider(leader_qflags, minfo).get())};
|
||||
// Run our first, "leader" query
|
||||
DeciderInfo minfo{};
|
||||
auto enq{make_enquire(expr, MU_MSG_FIELD_ID_DATE, leader_qflags)};
|
||||
const auto mset{
|
||||
enq.get_mset(0, maxnum, {}, make_leader_decider(leader_qflags, minfo).get())};
|
||||
|
||||
// Gather the thread-ids we found
|
||||
mset.fetch();
|
||||
for (auto it = mset.begin(); it != mset.end(); ++it) {
|
||||
auto thread_id{opt_string(it.get_document(), MU_MSG_FIELD_ID_THREAD_ID)};
|
||||
if (thread_id)
|
||||
minfo.thread_ids.emplace(std::move(*thread_id));
|
||||
}
|
||||
// Gather the thread-ids we found
|
||||
mset.fetch();
|
||||
for (auto it = mset.begin(); it != mset.end(); ++it) {
|
||||
auto thread_id{opt_string(it.get_document(), MU_MSG_FIELD_ID_THREAD_ID)};
|
||||
if (thread_id)
|
||||
minfo.thread_ids.emplace(std::move(*thread_id));
|
||||
}
|
||||
|
||||
// Now, determine the "related query".
|
||||
//
|
||||
// In the threaded-case, we search among _all_ messages, since complete
|
||||
// threads are preferred; no need to sort in that case since the search
|
||||
// is unlimited and the sorting happens during threading.
|
||||
auto r_enq{make_related_enquire(minfo.thread_ids,
|
||||
threading ? MU_MSG_FIELD_ID_NONE : sortfieldid, qflags)};
|
||||
const auto r_mset{r_enq.get_mset(0, threading ? store_.size() : maxnum,
|
||||
{}, make_related_decider(qflags, minfo).get())};
|
||||
auto qres{QueryResults{r_mset, std::move(minfo.matches)}};
|
||||
return threading ? run_threaded(std::move(qres), r_enq, qflags) : qres;
|
||||
// Now, determine the "related query".
|
||||
//
|
||||
// In the threaded-case, we search among _all_ messages, since complete
|
||||
// threads are preferred; no need to sort in that case since the search
|
||||
// is unlimited and the sorting happens during threading.
|
||||
auto r_enq{make_related_enquire(minfo.thread_ids,
|
||||
threading ? MU_MSG_FIELD_ID_NONE : sortfieldid,
|
||||
qflags)};
|
||||
const auto r_mset{r_enq.get_mset(0,
|
||||
threading ? store_.size() : maxnum,
|
||||
{},
|
||||
make_related_decider(qflags, minfo).get())};
|
||||
auto qres{QueryResults{r_mset, std::move(minfo.matches)}};
|
||||
return threading ? run_threaded(std::move(qres), r_enq, qflags) : qres;
|
||||
}
|
||||
|
||||
|
||||
Option<QueryResults>
|
||||
Query::Private::run (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags, size_t maxnum) const
|
||||
Query::Private::run(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
QueryFlags qflags,
|
||||
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{sortfieldid == MU_MSG_FIELD_ID_NONE ?
|
||||
MU_MSG_FIELD_ID_DATE : sortfieldid };
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
const auto eff_sortfield{sortfieldid == MU_MSG_FIELD_ID_NONE ? MU_MSG_FIELD_ID_DATE
|
||||
: sortfieldid};
|
||||
#pragma GCC diagnostic pop
|
||||
if (any_of(qflags & QueryFlags::IncludeRelated))
|
||||
return run_related (expr, eff_sortfield, qflags, eff_maxnum);
|
||||
else
|
||||
return run_singular(expr, eff_sortfield, qflags, eff_maxnum);
|
||||
if (any_of(qflags & QueryFlags::IncludeRelated))
|
||||
return run_related(expr, eff_sortfield, qflags, eff_maxnum);
|
||||
else
|
||||
return run_singular(expr, eff_sortfield, qflags, eff_maxnum);
|
||||
}
|
||||
|
||||
|
||||
Option<QueryResults>
|
||||
Query::run (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||
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);
|
||||
Query::run(const std::string& expr,
|
||||
MuMsgFieldId sortfieldid,
|
||||
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);
|
||||
|
||||
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)};
|
||||
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, sortfieldid, qflags, maxnum);
|
||||
return priv_->run(expr, sortfieldid, qflags, maxnum);
|
||||
|
||||
} catch (...) {
|
||||
return Nothing;
|
||||
return Nothing;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
Query::count (const std::string& expr) const
|
||||
Query::count(const std::string& expr) const
|
||||
{
|
||||
return xapian_try([&] {
|
||||
const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})};
|
||||
auto mset{enq.get_mset(0, priv_->store_.size())};
|
||||
mset.fetch();
|
||||
return mset.size();
|
||||
}, 0);
|
||||
return xapian_try(
|
||||
[&] {
|
||||
const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})};
|
||||
auto mset{enq.get_mset(0, priv_->store_.size())};
|
||||
mset.fetch();
|
||||
return mset.size();
|
||||
},
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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)};
|
||||
for (auto&& w: warns)
|
||||
g_warning ("query warning: %s", to_string(w).c_str());
|
||||
WarningVec warns;
|
||||
const auto tree{priv_->parser_.parse(expr, warns)};
|
||||
for (auto&& w : warns)
|
||||
g_warning("query warning: %s", to_string(w).c_str());
|
||||
|
||||
if (xapian)
|
||||
return xapian_query(tree).get_description();
|
||||
else
|
||||
return to_string(tree);
|
||||
if (xapian)
|
||||
return xapian_query(tree).get_description();
|
||||
else
|
||||
return to_string(tree);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user