lib: Add regexp searching for mid: prefix

The bulk of the change is passing in the field options to the regexp
field processor, so that we can properly handle the
fallback (non-regexp case).
This commit is contained in:
David Bremner 2017-02-15 08:58:28 -04:00
parent 77c9ec1fdd
commit eab365c742
4 changed files with 48 additions and 14 deletions

View file

@ -262,7 +262,8 @@ prefix_t prefix_table[] = {
{ "tag", "K", NOTMUCH_FIELD_EXTERNAL }, { "tag", "K", NOTMUCH_FIELD_EXTERNAL },
{ "is", "K", NOTMUCH_FIELD_EXTERNAL }, { "is", "K", NOTMUCH_FIELD_EXTERNAL },
{ "id", "Q", NOTMUCH_FIELD_EXTERNAL }, { "id", "Q", NOTMUCH_FIELD_EXTERNAL },
{ "mid", "Q", NOTMUCH_FIELD_EXTERNAL }, { "mid", "Q", NOTMUCH_FIELD_EXTERNAL |
NOTMUCH_FIELD_PROCESSOR },
{ "path", "P", NOTMUCH_FIELD_EXTERNAL }, { "path", "P", NOTMUCH_FIELD_EXTERNAL },
{ "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL }, { "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL },
/* /*
@ -313,7 +314,8 @@ _setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch)
else if (STRNCMP_LITERAL(prefix->name, "query") == 0) else if (STRNCMP_LITERAL(prefix->name, "query") == 0)
fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release (); fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release ();
else else
fp = (new RegexpFieldProcessor (prefix->name, *notmuch->query_parser, notmuch))->release (); fp = (new RegexpFieldProcessor (prefix->name, prefix->flags,
*notmuch->query_parser, notmuch))->release ();
/* we treat all field-processor fields as boolean in order to get the raw input */ /* we treat all field-processor fields as boolean in order to get the raw input */
notmuch->query_parser->add_boolean_prefix (prefix->name, fp); notmuch->query_parser->add_boolean_prefix (prefix->name, fp);

View file

@ -135,13 +135,21 @@ static inline Xapian::valueno _find_slot (std::string prefix)
return NOTMUCH_VALUE_FROM; return NOTMUCH_VALUE_FROM;
else if (prefix == "subject") else if (prefix == "subject")
return NOTMUCH_VALUE_SUBJECT; return NOTMUCH_VALUE_SUBJECT;
else if (prefix == "mid")
return NOTMUCH_VALUE_MESSAGE_ID;
else else
throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'"); throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'");
} }
RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix, Xapian::QueryParser &parser_, notmuch_database_t *notmuch_) RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix,
: slot (_find_slot (prefix)), term_prefix (_find_prefix (prefix.c_str ())), notmuch_field_flag_t options_,
parser (parser_), notmuch (notmuch_) Xapian::QueryParser &parser_,
notmuch_database_t *notmuch_)
: slot (_find_slot (prefix)),
term_prefix (_find_prefix (prefix.c_str ())),
options (options_),
parser (parser_),
notmuch (notmuch_)
{ {
}; };
@ -161,16 +169,22 @@ RegexpFieldProcessor::operator() (const std::string & str)
throw Xapian::QueryParserError ("unmatched regex delimiter in '" + str + "'"); throw Xapian::QueryParserError ("unmatched regex delimiter in '" + str + "'");
} }
} else { } else {
/* TODO replace this with a nicer API level triggering of if (options & NOTMUCH_FIELD_PROBABILISTIC) {
* phrase parsing, when possible */ /* TODO replace this with a nicer API level triggering of
std::string query_str; * phrase parsing, when possible */
std::string query_str;
if (str.find (' ') != std::string::npos) if (str.find (' ') != std::string::npos)
query_str = '"' + str + '"'; query_str = '"' + str + '"';
else else
query_str = str; query_str = str;
return parser.parse_query (query_str, NOTMUCH_QUERY_PARSER_FLAGS, term_prefix); return parser.parse_query (query_str, NOTMUCH_QUERY_PARSER_FLAGS, term_prefix);
} else {
/* Boolean prefix */
std::string term = term_prefix + str;
return Xapian::Query (term);
}
} }
} }
#endif #endif

View file

@ -65,11 +65,13 @@ class RegexpFieldProcessor : public Xapian::FieldProcessor {
protected: protected:
Xapian::valueno slot; Xapian::valueno slot;
std::string term_prefix; std::string term_prefix;
notmuch_field_flag_t options;
Xapian::QueryParser &parser; Xapian::QueryParser &parser;
notmuch_database_t *notmuch; notmuch_database_t *notmuch;
public: public:
RegexpFieldProcessor (std::string prefix, Xapian::QueryParser &parser_, notmuch_database_t *notmuch_); RegexpFieldProcessor (std::string prefix, notmuch_field_flag_t options,
Xapian::QueryParser &parser_, notmuch_database_t *notmuch_);
~RegexpFieldProcessor () { }; ~RegexpFieldProcessor () { };

View file

@ -104,4 +104,20 @@ Query string was: from:/unbalanced[/
EOF EOF
test_expect_equal_file EXPECTED OUTPUT test_expect_equal_file EXPECTED OUTPUT
test_begin_subtest "empty mid search"
notmuch search --output=messages mid:yoom > OUTPUT
cp /dev/null EXPECTED
test_expect_equal_file EXPECTED OUTPUT
test_begin_subtest "non-empty mid regex search"
notmuch search --output=messages mid:/yoom/ > OUTPUT
test_expect_equal_file cworth.msg-ids OUTPUT
test_begin_subtest "combine regexp mid and subject"
notmuch search subject:/-C/ and mid:/y..m/ | notmuch_search_sanitize > OUTPUT
cat <<EOF > EXPECTED
thread:XXX 2009-11-18 [1/2] Carl Worth| Jan Janak; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
EOF
test_expect_equal_file EXPECTED OUTPUT
test_done test_done