query-parser: tidy up

Remove "Data", and use Field directly.
This commit is contained in:
Dirk-Jan C. Binnema
2022-06-12 19:44:00 +03:00
parent 1a84a57e05
commit 48695a1981
7 changed files with 139 additions and 244 deletions

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2017-2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public License
@ -17,9 +17,7 @@
** 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <xapian.h>
#include "mu-xapian.hh"
@ -30,24 +28,33 @@ using namespace Mu;
static Xapian::Query
xapian_query_op(const Mu::Tree& tree)
{
Xapian::Query::op op;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (tree.node.type) {
case Node::Type::OpNot: // OpNot x ::= <all> AND NOT x
if (tree.node.type == Node::Type::OpNot) { // OpNot x ::= <all> AND NOT x
if (tree.children.size() != 1)
throw std::runtime_error("invalid # of children");
return Xapian::Query(Xapian::Query::OP_AND_NOT,
Xapian::Query::MatchAll,
xapian_query(tree.children.front()));
case Node::Type::OpAnd: op = Xapian::Query::OP_AND; break;
case Node::Type::OpOr: op = Xapian::Query::OP_OR; break;
case Node::Type::OpXor: op = Xapian::Query::OP_XOR; break;
case Node::Type::OpAndNot: op = Xapian::Query::OP_AND_NOT; break;
default: throw Mu::Error(Error::Code::Internal, "invalid op"); // bug
Xapian::Query::MatchAll,
xapian_query(tree.children.front()));
}
const auto op = std::invoke([](Node::Type ntype) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (ntype) {
case Node::Type::OpAnd:
return Xapian::Query::OP_AND;
case Node::Type::OpOr:
return Xapian::Query::OP_OR;
case Node::Type::OpXor:
return Xapian::Query::OP_XOR;
case Node::Type::OpAndNot:
return Xapian::Query::OP_AND_NOT;
case Node::Type::OpNot:
default:
throw Mu::Error(Error::Code::Internal, "invalid op"); // bug
}
#pragma GCC diagnostic pop
}, tree.node.type);
std::vector<Xapian::Query> childvec;
for (const auto& subtree : tree.children)
childvec.emplace_back(xapian_query(subtree));
@ -56,33 +63,37 @@ xapian_query_op(const Mu::Tree& tree)
}
static Xapian::Query
make_query(const Value* val, const std::string& str, bool maybe_wildcard)
make_query(const FieldValue& fval, bool maybe_wildcard)
{
const auto vlen{str.length()};
if (!maybe_wildcard || vlen <= 1 || str[vlen - 1] != '*')
return Xapian::Query(val->prefix + str);
const auto vlen{fval.value().length()};
if (!maybe_wildcard || vlen <= 1 || fval.value()[vlen - 1] != '*')
return Xapian::Query(fval.field().xapian_term(fval.value()));
else
return Xapian::Query(Xapian::Query::OP_WILDCARD,
val->prefix + str.substr(0, vlen - 1));
fval.field().xapian_term(fval.value().substr(0, vlen - 1)));
}
static Xapian::Query
xapian_query_value(const Mu::Tree& tree)
{
const auto v = dynamic_cast<Value*>(tree.node.data.get());
if (!v->phrase)
return make_query(v, v->value, true /*maybe-wildcard*/);
// indexable field implies it can be use with a phrase search.
const auto& field_val{tree.node.field_val.value()};
if (!field_val.field().is_indexable_term()) { //
/* not an indexable field; no extra magic needed*/
return make_query(field_val, true /*maybe-wildcard*/);
}
const auto parts = split(v->value, " ");
const auto parts{split(field_val.value(), " ")};
if (parts.empty())
return Xapian::Query::MatchNothing; // shouldn't happen
if (parts.size() == 1)
return make_query(v, parts.front(), true /*maybe-wildcard*/);
else if (parts.size() == 1)
return make_query(field_val, true /*maybe-wildcard*/);
std::vector<Xapian::Query> phvec;
for (const auto& p : parts)
phvec.emplace_back(make_query(v, p, false /*no wildcards*/));
for (const auto& p : parts) {
FieldValue fv{field_val.field_id, p};
phvec.emplace_back(make_query(fv, false /*no wildcards*/));
}
return Xapian::Query(Xapian::Query::OP_PHRASE, phvec.begin(), phvec.end());
}
@ -90,12 +101,12 @@ xapian_query_value(const Mu::Tree& tree)
static Xapian::Query
xapian_query_range(const Mu::Tree& tree)
{
const auto r{dynamic_cast<Range*>(tree.node.data.get())};
const auto& field_val{tree.node.field_val.value()};
return Xapian::Query(Xapian::Query::OP_VALUE_RANGE,
(Xapian::valueno)r->id,
r->lower,
r->upper);
field_val.field().value_no(),
field_val.range().first,
field_val.range().second);
}
Xapian::Query
@ -104,15 +115,20 @@ Mu::xapian_query(const Mu::Tree& tree)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (tree.node.type) {
case Node::Type::Empty: return Xapian::Query();
case Node::Type::Empty:
return Xapian::Query();
case Node::Type::OpNot:
case Node::Type::OpAnd:
case Node::Type::OpOr:
case Node::Type::OpXor:
case Node::Type::OpAndNot: return xapian_query_op(tree);
case Node::Type::Value: return xapian_query_value(tree);
case Node::Type::Range: return xapian_query_range(tree);
default: throw Mu::Error(Error::Code::Internal, "invalid query"); // bug
case Node::Type::OpAndNot:
return xapian_query_op(tree);
case Node::Type::Value:
return xapian_query_value(tree);
case Node::Type::Range:
return xapian_query_range(tree);
default:
throw Mu::Error(Error::Code::Internal, "invalid query"); // bug
}
#pragma GCC diagnostic pop
}