summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Masurel <paul.masurel@gmail.com>2018-08-20 09:21:32 +0900
committerPaul Masurel <paul.masurel@gmail.com>2018-08-20 09:21:32 +0900
commita0a284fe91c0ca16961875959300fcf917327c43 (patch)
tree241bcbc9d3b03d26c8a32c7215e746c4cf6ff653 /src
parent0feeef26843e17d731cd06080d8f2a8f7819bd90 (diff)
Added a full fledge empty query and relyign on it in QueryParser, instead of using an empty clause.
Diffstat (limited to 'src')
-rw-r--r--src/query/empty_query.rs81
-rw-r--r--src/query/mod.rs3
-rw-r--r--src/query/query_parser/query_parser.rs33
-rw-r--r--src/query/scorer.rs45
4 files changed, 111 insertions, 51 deletions
diff --git a/src/query/empty_query.rs b/src/query/empty_query.rs
new file mode 100644
index 0000000..06c15c3
--- /dev/null
+++ b/src/query/empty_query.rs
@@ -0,0 +1,81 @@
+use super::Scorer;
+use DocSet;
+use Score;
+use DocId;
+use query::Query;
+use Result;
+use Searcher;
+use query::Weight;
+use SegmentReader;
+
+/// `EmptyQuery` is a dummy `Query` in which no document matches.
+///
+/// It is useful for tests and handling edge cases.
+#[derive(Clone, Debug)]
+pub struct EmptyQuery;
+
+impl Query for EmptyQuery {
+ fn weight(&self, _searcher: &Searcher, _scoring_enabled: bool) -> Result<Box<Weight>> {
+ Ok(Box::new(EmptyWeight))
+ }
+
+ fn count(&self, _searcher: &Searcher) -> Result<usize> {
+ Ok(0)
+ }
+}
+
+/// `EmptyWeight` is a dummy `Weight` in which no document matches.
+///
+/// It is useful for tests and handling edge cases.
+pub struct EmptyWeight;
+impl Weight for EmptyWeight {
+ fn scorer(&self, _reader: &SegmentReader) -> Result<Box<Scorer>> {
+ Ok(Box::new(EmptyScorer))
+ }
+}
+
+/// `EmptyScorer` is a dummy `Scorer` in which no document matches.
+///
+/// It is useful for tests and handling edge cases.
+pub struct EmptyScorer;
+
+impl DocSet for EmptyScorer {
+ fn advance(&mut self) -> bool {
+ false
+ }
+
+ fn doc(&self) -> DocId {
+ panic!(
+ "You may not call .doc() on a scorer \
+ where the last call to advance() did not return true."
+ );
+ }
+
+ fn size_hint(&self) -> u32 {
+ 0
+ }
+}
+
+impl Scorer for EmptyScorer {
+ fn score(&mut self) -> Score {
+ 0f32
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use query::EmptyScorer;
+ use DocSet;
+
+ #[test]
+ fn test_empty_scorer() {
+ let mut empty_scorer = EmptyScorer;
+ assert!(!empty_scorer.advance());
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_empty_scorer_panic_on_doc_call() {
+ EmptyScorer.doc();
+ }
+}
diff --git a/src/query/mod.rs b/src/query/mod.rs
index 7b6368c..7546465 100644
--- a/src/query/mod.rs
+++ b/src/query/mod.rs
@@ -3,6 +3,7 @@ Query
*/
mod all_query;
+mod empty_query;
mod automaton_weight;
mod bitset;
mod bm25;
@@ -34,6 +35,7 @@ pub use self::union::Union;
pub use self::vec_docset::VecDocSet;
pub use self::all_query::{AllQuery, AllScorer, AllWeight};
+pub use self::empty_query::{EmptyQuery, EmptyWeight, EmptyScorer};
pub use self::automaton_weight::AutomatonWeight;
pub use self::bitset::BitSetDocSet;
pub use self::boolean_query::BooleanQuery;
@@ -49,7 +51,6 @@ pub use self::range_query::RangeQuery;
pub use self::regex_query::RegexQuery;
pub use self::reqopt_scorer::RequiredOptionalScorer;
pub use self::scorer::ConstScorer;
-pub use self::scorer::EmptyScorer;
pub use self::scorer::Scorer;
pub use self::term_query::TermQuery;
pub use self::weight::Weight;
diff --git a/src/query/query_parser/query_parser.rs b/src/query/query_parser/query_parser.rs
index 0b41334..abe6b40 100644
--- a/src/query/query_parser/query_parser.rs
+++ b/src/query/query_parser/query_parser.rs
@@ -18,6 +18,7 @@ use std::ops::Bound;
use std::str::FromStr;
use tokenizer::TokenizerManager;
use combine::Parser;
+use query::EmptyQuery;
/// Possible error that may happen when parsing a query.
@@ -438,11 +439,15 @@ fn convert_literal_to_query(logical_literal: LogicalLiteral) -> Box<Query> {
fn convert_to_query(logical_ast: LogicalAST) -> Box<Query> {
match logical_ast {
LogicalAST::Clause(clause) => {
- let occur_subqueries = clause
- .into_iter()
- .map(|(occur, subquery)| (occur, convert_to_query(subquery)))
- .collect::<Vec<_>>();
- Box::new(BooleanQuery::from(occur_subqueries))
+ if clause.is_empty() {
+ Box::new(EmptyQuery)
+ } else {
+ let occur_subqueries = clause
+ .into_iter()
+ .map(|(occur, subquery)| (occur, convert_to_query(subquery)))
+ .collect::<Vec<_>>();
+ Box::new(BooleanQuery::from(occur_subqueries))
+ }
}
LogicalAST::Leaf(logical_literal) => convert_literal_to_query(*logical_literal),
}
@@ -542,6 +547,24 @@ mod test {
}
#[test]
+ pub fn test_parse_query_empty() {
+ test_parse_query_to_logical_ast_helper(
+ "",
+ "<emptyclause>",
+ false,
+ );
+ test_parse_query_to_logical_ast_helper(
+ " ",
+ "<emptyclause>",
+ false,
+ );
+ let query_parser = make_query_parser();
+ let query_result = query_parser.parse_query("");
+ let query = query_result.unwrap();
+ assert_eq!(format!("{:?}", query), "EmptyQuery");
+ }
+
+ #[test]
pub fn test_parse_query_ints() {
let query_parser = make_query_parser();
assert!(query_parser.parse_query("signed:2324").is_ok());
diff --git a/src/query/scorer.rs b/src/query/scorer.rs
index a94b03a..186e75a 100644
--- a/src/query/scorer.rs
+++ b/src/query/scorer.rs
@@ -50,33 +50,6 @@ impl Scorer for Box<Scorer> {
}
}
-/// `EmptyScorer` is a dummy `Scorer` in which no document matches.
-///
-/// It is useful for tests and handling edge cases.
-pub struct EmptyScorer;
-
-impl DocSet for EmptyScorer {
- fn advance(&mut self) -> bool {
- false
- }
-
- fn doc(&self) -> DocId {
- panic!(
- "You may not call .doc() on a scorer \
- where the last call to advance() did not return true."
- );
- }
-
- fn size_hint(&self) -> u32 {
- 0
- }
-}
-
-impl Scorer for EmptyScorer {
- fn score(&mut self) -> Score {
- 0f32
- }
-}
/// Wraps a `DocSet` and simply returns a constant `Scorer`.
/// The `ConstScorer` is useful if you have a `DocSet` where
@@ -135,21 +108,3 @@ impl<TDocSet: DocSet + 'static> Scorer for ConstScorer<TDocSet> {
1f32
}
}
-
-#[cfg(test)]
-mod tests {
- use super::EmptyScorer;
- use DocSet;
-
- #[test]
- fn test_empty_scorer() {
- let mut empty_scorer = EmptyScorer;
- assert!(!empty_scorer.advance());
- }
-
- #[test]
- #[should_panic]
- fn test_empty_scorer_panic_on_doc_call() {
- EmptyScorer.doc();
- }
-}