lib: Add regexp searching for mid: prefix
authorDavid Bremner <david@tethera.net>
Wed, 15 Feb 2017 12:58:28 +0000 (08:58 -0400)
committerDavid Bremner <david@tethera.net>
Tue, 9 May 2017 10:44:15 +0000 (07:44 -0300)
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).

lib/database.cc
lib/regexp-fields.cc
lib/regexp-fields.h
test/T650-regexp-query.sh

index 5bc131a35d44a8621d836ab3c2e86ad33c6f793d..49b3849c32586124db4364c4c6815a25316f2bc7 100644 (file)
@@ -262,7 +262,8 @@ prefix_t prefix_table[] = {
     { "tag",                   "K",            NOTMUCH_FIELD_EXTERNAL },
     { "is",                    "K",            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 },
     { "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)
            fp = (new QueryFieldProcessor (*notmuch->query_parser, notmuch))->release ();
        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 */
        notmuch->query_parser->add_boolean_prefix (prefix->name, fp);
index 1651677cd8638b759a9f96838237a98aa2ef5af2..7ae55e70016c1f5e26c8b3c47dc1a5a5624e5b2d 100644 (file)
@@ -135,13 +135,21 @@ static inline Xapian::valueno _find_slot (std::string prefix)
        return NOTMUCH_VALUE_FROM;
     else if (prefix == "subject")
        return NOTMUCH_VALUE_SUBJECT;
+    else if (prefix == "mid")
+       return NOTMUCH_VALUE_MESSAGE_ID;
     else
        throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'");
 }
 
-RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix, Xapian::QueryParser &parser_, notmuch_database_t *notmuch_)
-       : slot (_find_slot (prefix)), term_prefix (_find_prefix (prefix.c_str ())),
-         parser (parser_), notmuch (notmuch_)
+RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix,
+                                           notmuch_field_flag_t options_,
+                                           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 + "'");
        }
     } else {
-       /* TODO replace this with a nicer API level triggering of
-        * phrase parsing, when possible */
-       std::string query_str;
+       if (options & NOTMUCH_FIELD_PROBABILISTIC) {
+           /* TODO replace this with a nicer API level triggering of
+            * phrase parsing, when possible */
+           std::string query_str;
 
-       if (str.find (' ') != std::string::npos)
-           query_str = '"' + str + '"';
-       else
-           query_str = str;
+           if (str.find (' ') != std::string::npos)
+               query_str = '"' + str + '"';
+           else
+               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
index a4ba7ad8412cebbf8a2104f4058548abc277a8fc..d5f93445400d875585f7c1e788ae03ab338d3374 100644 (file)
@@ -65,11 +65,13 @@ class RegexpFieldProcessor : public Xapian::FieldProcessor {
  protected:
     Xapian::valueno slot;
     std::string term_prefix;
+    notmuch_field_flag_t options;
     Xapian::QueryParser &parser;
     notmuch_database_t *notmuch;
 
  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 () { };
 
index 9599c104d452f9d8b0f331017b500751e808138f..27fc9ab9831dba70672a167e28f0f541215e2b89 100755 (executable)
@@ -104,4 +104,20 @@ Query string was: from:/unbalanced[/
 EOF
 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