diff options
| author | David Bremner <david@tethera.net> | 2017-08-27 15:54:50 -0300 |
|---|---|---|
| committer | David Bremner <david@tethera.net> | 2017-08-27 15:54:50 -0300 |
| commit | a565f71e1c160431ff99f088bc8fc08d367603a2 (patch) | |
| tree | 2f7c33d7296e15b2c33f6ede436d412c812c3f15 /lib/regexp-fields.cc | |
| parent | 00f87faf4bc19e90e19b8b27c13845efb6a68152 (diff) | |
| parent | 6354745dcd6505c5f12c185a29c25a8d1c240595 (diff) | |
Merge tag 'debian/0.25-6' into debian/stretch-backports
Diffstat (limited to 'lib/regexp-fields.cc')
| -rw-r--r-- | lib/regexp-fields.cc | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/lib/regexp-fields.cc b/lib/regexp-fields.cc index 1651677c..084bc8c0 100644 --- a/lib/regexp-fields.cc +++ b/lib/regexp-fields.cc @@ -135,42 +135,76 @@ 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 + "'"); + return Xapian::BAD_VALUENO; } -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_) { }; Xapian::Query RegexpFieldProcessor::operator() (const std::string & str) { - if (str.size () == 0) - return Xapian::Query(Xapian::Query::OP_AND_NOT, + if (str.empty ()) { + if (options & NOTMUCH_FIELD_PROBABILISTIC) { + return Xapian::Query(Xapian::Query::OP_AND_NOT, Xapian::Query::MatchAll, Xapian::Query (Xapian::Query::OP_WILDCARD, term_prefix)); + } else { + return Xapian::Query (term_prefix); + } + } if (str.at (0) == '/') { - if (str.at (str.size () - 1) == '/'){ - RegexpPostingSource *postings = new RegexpPostingSource (slot, str.substr(1,str.size () - 2)); - return Xapian::Query (postings->release ()); + if (str.length() > 1 && str.at (str.size () - 1) == '/'){ + std::string regexp_str = str.substr(1,str.size () - 2); + if (slot != Xapian::BAD_VALUENO) { + RegexpPostingSource *postings = new RegexpPostingSource (slot, regexp_str); + return Xapian::Query (postings->release ()); + } else { + std::vector<std::string> terms; + regex_t regexp; + + compile_regex(regexp, regexp_str.c_str ()); + for (Xapian::TermIterator it = notmuch->xapian_db->allterms_begin (term_prefix); + it != notmuch->xapian_db->allterms_end (); ++it) { + if (regexec (®exp, (*it).c_str () + term_prefix.size(), + 0, NULL, 0) == 0) + terms.push_back(*it); + } + return Xapian::Query (Xapian::Query::OP_OR, terms.begin(), terms.end()); + } } else { 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 |
