From cbbc505268e8fa994fa21383ed49a91b2e923f66 Mon Sep 17 00:00:00 2001 From: Mike McCandless Date: Fri, 8 Jul 2016 13:07:54 -0400 Subject: [PATCH] LUCENE-7276: MatchNoDocsQuery now inclues an optional reason for why it was used --- lucene/CHANGES.txt | 3 ++ .../apache/lucene/document/BinaryPoint.java | 2 +- .../apache/lucene/search/BooleanQuery.java | 4 +- .../lucene/search/MatchNoDocsQuery.java | 17 ++++++- .../lucene/search/MultiPhraseQuery.java | 2 +- .../org/apache/lucene/search/PhraseQuery.java | 2 +- .../lucene/search/TestMatchNoDocsQuery.java | 46 +++++++++++++++---- .../apache/lucene/search/join/JoinUtil.java | 4 +- .../lucene/queries/CommonTermsQuery.java | 2 +- .../queryparser/simple/SimpleQueryParser.java | 2 +- .../precedence/TestPrecedenceQueryParser.java | 23 ++++++++-- .../standard/TestMultiFieldQPHelper.java | 24 ++++++++-- .../flexible/standard/TestQPHelper.java | 36 ++++++++++----- .../queryparser/util/QueryParserTestBase.java | 37 ++++++++++----- .../apache/lucene/document/LatLonPoint.java | 4 +- 15 files changed, 154 insertions(+), 54 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index f609e837b1d..bed9b80601e 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -89,6 +89,9 @@ Improvements control whether to split on whitespace prior to text analysis. Default behavior remains unchanged: split-on-whitespace=true. (Steve Rowe) +* LUCENE-7276: MatchNoDocsQuery now includes an optional reason for + why it was used (Jim Ferenczi via Mike McCandless) + Optimizations * LUCENE-7330, LUCENE-7339: Speed up conjunction queries. (Adrien Grand) diff --git a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java index 3b0a0e97591..338817081d1 100644 --- a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java @@ -212,7 +212,7 @@ public final class BinaryPoint extends Field { if (bytesPerDim == -1) { // There are no points, and we cannot guess the bytesPerDim here, so we return an equivalent query: - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("empty BinaryPoint.newSetQuery"); } // Don't unexpectedly change the user's incoming values array: diff --git a/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java b/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java index b48f80146ce..c22b1bb5ef4 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java @@ -207,7 +207,7 @@ public class BooleanQuery extends Query implements Iterable { @Override public Query rewrite(IndexReader reader) throws IOException { if (clauses.size() == 0) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("empty BooleanQuery"); } // optimize 1-clause queries @@ -226,7 +226,7 @@ public class BooleanQuery extends Query implements Iterable { return new BoostQuery(new ConstantScoreQuery(query), 0); case MUST_NOT: // no positive clauses - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("pure negative BooleanQuery"); default: throw new AssertionError(); } diff --git a/lucene/core/src/java/org/apache/lucene/search/MatchNoDocsQuery.java b/lucene/core/src/java/org/apache/lucene/search/MatchNoDocsQuery.java index d373b4672dd..825e082aa3b 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MatchNoDocsQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/MatchNoDocsQuery.java @@ -28,6 +28,19 @@ import org.apache.lucene.index.Term; */ public class MatchNoDocsQuery extends Query { + + private final String reason; + + /** Default constructor */ + public MatchNoDocsQuery() { + this(""); + } + + /** Provides a reason explaining why this query was used */ + public MatchNoDocsQuery(String reason) { + this.reason = reason; + } + @Override public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException { return new Weight(this) { @@ -37,7 +50,7 @@ public class MatchNoDocsQuery extends Query { @Override public Explanation explain(LeafReaderContext context, int doc) throws IOException { - return Explanation.noMatch(""); + return Explanation.noMatch(reason); } @Override @@ -73,7 +86,7 @@ public class MatchNoDocsQuery extends Query { @Override public String toString(String field) { - return ""; + return "MatchNoDocsQuery(\"" + reason + "\")"; } @Override diff --git a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java index 2d5c3892aba..00af26c97cf 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java @@ -317,7 +317,7 @@ public class MultiPhraseQuery extends Query { @Override public Query rewrite(IndexReader reader) throws IOException { if (termArrays.length == 0) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("empty MultiPhraseQuery"); } else if (termArrays.length == 1) { // optimize one-term case Term[] terms = termArrays[0]; BooleanQuery.Builder builder = new BooleanQuery.Builder(); diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java index 459d6648abf..64c09463473 100644 --- a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java @@ -271,7 +271,7 @@ public class PhraseQuery extends Query { @Override public Query rewrite(IndexReader reader) throws IOException { if (terms.length == 0) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("empty PhraseQuery"); } else if (terms.length == 1) { return new TermQuery(terms[0]); } else if (positions[0] != 0) { diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMatchNoDocsQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestMatchNoDocsQuery.java index 0a97c582c70..55514dcb4e3 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestMatchNoDocsQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestMatchNoDocsQuery.java @@ -23,10 +23,10 @@ import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; import org.apache.lucene.store.Directory; - import org.apache.lucene.util.LuceneTestCase; /** @@ -41,23 +41,52 @@ public class TestMatchNoDocsQuery extends LuceneTestCase { analyzer = new MockAnalyzer(random()); } + public void testSimple() throws Exception { + MatchNoDocsQuery query = new MatchNoDocsQuery(); + assertEquals(query.toString(), "MatchNoDocsQuery(\"\")"); + query = new MatchNoDocsQuery("field 'title' not found"); + assertEquals(query.toString(), "MatchNoDocsQuery(\"field 'title' not found\")"); + Query rewrite = query.rewrite(null); + assertTrue(rewrite instanceof MatchNoDocsQuery); + assertEquals(rewrite.toString(), "MatchNoDocsQuery(\"field 'title' not found\")"); + } + public void testQuery() throws Exception { Directory dir = newDirectory(); IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig(analyzer).setMaxBufferedDocs(2).setMergePolicy(newLogMergePolicy())); addDoc("one", iw); addDoc("two", iw); - addDoc("three four", iw); + addDoc("three", iw); IndexReader ir = DirectoryReader.open(iw); + IndexSearcher searcher = new IndexSearcher(ir); + + Query query = new MatchNoDocsQuery("field not found"); + assertEquals(searcher.count(query), 0); - IndexSearcher is = newSearcher(ir); ScoreDoc[] hits; - - hits = is.search(new MatchNoDocsQuery(), 1000).scoreDocs; + hits = searcher.search(new MatchNoDocsQuery(), 1000).scoreDocs; assertEquals(0, hits.length); + assertEquals(query.toString(), "MatchNoDocsQuery(\"field not found\")"); - MatchNoDocsQuery mndq = new MatchNoDocsQuery(); - hits = is.search(mndq, 1000).scoreDocs; + BooleanQuery.Builder bq = new BooleanQuery.Builder(); + bq.add(new BooleanClause(new TermQuery(new Term("key", "five")), BooleanClause.Occur.SHOULD)); + bq.add(new BooleanClause(new MatchNoDocsQuery("field not found"), BooleanClause.Occur.MUST)); + query = bq.build(); + assertEquals(searcher.count(query), 0); + hits = searcher.search(new MatchNoDocsQuery(), 1000).scoreDocs; assertEquals(0, hits.length); + assertEquals(query.toString(), "key:five +MatchNoDocsQuery(\"field not found\")"); + + bq = new BooleanQuery.Builder(); + bq.add(new BooleanClause(new TermQuery(new Term("key", "one")), BooleanClause.Occur.SHOULD)); + bq.add(new BooleanClause(new MatchNoDocsQuery("field not found"), BooleanClause.Occur.SHOULD)); + query = bq.build(); + assertEquals(query.toString(), "key:one MatchNoDocsQuery(\"field not found\")"); + assertEquals(searcher.count(query), 1); + hits = searcher.search(query, 1000).scoreDocs; + Query rewrite = query.rewrite(ir); + assertEquals(1, hits.length); + assertEquals(rewrite.toString(), "key:one MatchNoDocsQuery(\"field not found\")"); iw.close(); ir.close(); @@ -77,5 +106,4 @@ public class TestMatchNoDocsQuery extends LuceneTestCase { doc.add(f); iw.addDocument(doc); } - } diff --git a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java index dd253431355..b0133e570da 100644 --- a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java +++ b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java @@ -494,7 +494,7 @@ public final class JoinUtil { int numSegments = indexReader.leaves().size(); final long valueCount; if (numSegments == 0) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments"); } else if (numSegments == 1) { // No need to use the ordinal map, because there is just one segment. ordinalMap = null; @@ -503,7 +503,7 @@ public final class JoinUtil { if (joinSortedDocValues != null) { valueCount = joinSortedDocValues.getValueCount(); } else { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("JoinUtil.createJoinQuery: no join values"); } } else { if (ordinalMap == null) { diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CommonTermsQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/CommonTermsQuery.java index febfc86275d..857f4d3fdbc 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/CommonTermsQuery.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/CommonTermsQuery.java @@ -119,7 +119,7 @@ public class CommonTermsQuery extends Query { @Override public Query rewrite(IndexReader reader) throws IOException { if (this.terms.isEmpty()) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("CommonTermsQuery with no terms"); } else if (this.terms.size() == 1) { return newTermQuery(this.terms.get(0), null); } diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java index b87541b31fb..3f9d9a42680 100644 --- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java +++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java @@ -150,7 +150,7 @@ public class SimpleQueryParser extends QueryBuilder { State state = new State(data, buffer, 0, data.length); parseSubQuery(state); if (state.top == null) { - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("empty string passed to query parser"); } else { return state.top; } diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/precedence/TestPrecedenceQueryParser.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/precedence/TestPrecedenceQueryParser.java index 5156f730b05..88e8b9b3cf2 100644 --- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/precedence/TestPrecedenceQueryParser.java +++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/precedence/TestPrecedenceQueryParser.java @@ -38,6 +38,7 @@ import org.apache.lucene.queryparser.util.QueryParserTestBase; // javadocs import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.FuzzyQuery; +import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.Query; @@ -61,7 +62,7 @@ import org.junit.BeforeClass; * * @see QueryParserTestBase */ -//TODO: refactor this to actually extend that class, overriding the tests +//TODO: refactor this to actually extend that class (QueryParserTestBase), overriding the tests //that it adjusts to fit the precedence requirement, adding its extra tests. public class TestPrecedenceQueryParser extends LuceneTestCase { @@ -166,6 +167,20 @@ public class TestPrecedenceQueryParser extends LuceneTestCase { } } + public void assertMatchNoDocsQuery(String queryString, Analyzer a) throws Exception { + assertMatchNoDocsQuery(getQuery(queryString, a)); + } + + public void assertMatchNoDocsQuery(Query query) throws Exception { + if (query instanceof MatchNoDocsQuery) { + // good + } else if (query instanceof BooleanQuery && ((BooleanQuery) query).clauses().size() == 0) { + // good + } else { + fail("expected MatchNoDocsQuery or an empty BooleanQuery but got: " + query); + } + } + public void assertWildcardQueryEquals(String query, boolean lowercase, String result) throws Exception { PrecedenceQueryParser qp = getParser(null); @@ -282,7 +297,7 @@ public class TestPrecedenceQueryParser extends LuceneTestCase { public void testNumber() throws Exception { // The numbers go away because SimpleAnalzyer ignores them - assertQueryEquals("3", null, ""); + assertMatchNoDocsQuery("3", null); assertQueryEquals("term 1.0 1 2", null, "term"); assertQueryEquals("term term1 term2", null, "term term term"); @@ -367,8 +382,8 @@ public class TestPrecedenceQueryParser extends LuceneTestCase { // QueryParser behavior assertQueryEquals("term AND NOT phrase term", qpAnalyzer, "(+term -(phrase1 phrase2)) term"); - assertQueryEquals("stop", qpAnalyzer, ""); - assertQueryEquals("stop OR stop AND stop", qpAnalyzer, ""); + assertMatchNoDocsQuery("stop", qpAnalyzer); + assertMatchNoDocsQuery("stop OR stop AND stop", qpAnalyzer); assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery); assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery); } diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java index 28e815dfd1c..95e299af848 100644 --- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java +++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java @@ -32,6 +32,7 @@ import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfi import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.store.Directory; @@ -55,9 +56,22 @@ public class TestMultiFieldQPHelper extends LuceneTestCase { assertStopQueryEquals("one stop", "b:one t:one"); assertStopQueryEquals("one (stop)", "b:one t:one"); assertStopQueryEquals("one ((stop))", "b:one t:one"); - assertStopQueryEquals("stop", ""); - assertStopQueryEquals("(stop)", ""); - assertStopQueryEquals("((stop))", ""); + assertStopQueryIsMatchNoDocsQuery("stop"); + assertStopQueryIsMatchNoDocsQuery("(stop)"); + assertStopQueryIsMatchNoDocsQuery("((stop))"); + } + + // verify parsing of query using a stopping analyzer + private void assertStopQueryIsMatchNoDocsQuery(String qtxt) throws Exception { + String[] fields = { "b", "t" }; + Occur occur[] = { Occur.SHOULD, Occur.SHOULD }; + TestQPHelper.QPTestAnalyzer a = new TestQPHelper.QPTestAnalyzer(); + StandardQueryParser mfqp = new StandardQueryParser(); + mfqp.setMultiFields(fields); + mfqp.setAnalyzer(a); + + Query q = mfqp.parse(qtxt, null); + assertTrue(q instanceof MatchNoDocsQuery); } // verify parsing of query using a stopping analyzer @@ -205,12 +219,12 @@ public class TestMultiFieldQPHelper extends LuceneTestCase { String[] queries6 = { "((+stop))", "+((stop))" }; q = QueryParserUtil.parse(queries6, fields, stopA); - assertEquals(" ", q.toString()); + assertEquals("MatchNoDocsQuery(\"\") MatchNoDocsQuery(\"\")", q.toString()); + //assertEquals(" ", q.toString()); String[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" }; q = QueryParserUtil.parse(queries7, fields, stopA); assertEquals("(b:one +b:more) (+t:two)", q.toString()); - } public void testStaticMethod2() throws QueryNodeException { diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java index e7d0c896e9a..91b799dc093 100644 --- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java +++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java @@ -53,8 +53,8 @@ import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor import org.apache.lucene.queryparser.flexible.messages.MessageImpl; import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler; import org.apache.lucene.queryparser.flexible.standard.nodes.WildcardQueryNode; -import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.FuzzyQuery; @@ -245,6 +245,20 @@ public class TestQPHelper extends LuceneTestCase { } } + public void assertMatchNoDocsQuery(String queryString, Analyzer a) throws Exception { + assertMatchNoDocsQuery(getQuery(queryString, a)); + } + + public void assertMatchNoDocsQuery(Query query) throws Exception { + if (query instanceof MatchNoDocsQuery) { + // good + } else if (query instanceof BooleanQuery && ((BooleanQuery) query).clauses().size() == 0) { + // good + } else { + fail("expected MatchNoDocsQuery or an empty BooleanQuery but got: " + query); + } + } + public void assertQueryEqualsAllowLeadingWildcard(String query, Analyzer a, String result) throws Exception { Query q = getQueryAllowLeadingWildcard(query, a); @@ -522,7 +536,7 @@ public class TestQPHelper extends LuceneTestCase { public void testNumber() throws Exception { // The numbers go away because SimpleAnalzyer ignores them - assertQueryEquals("3", null, ""); + assertMatchNoDocsQuery("3", null); assertQueryEquals("term 1.0 1 2", null, "term"); assertQueryEquals("term term1 term2", null, "term term term"); @@ -659,14 +673,14 @@ public class TestQPHelper extends LuceneTestCase { assertQueryEquals("term AND NOT phrase term", qpAnalyzer, "+term -(phrase1 phrase2) term"); - assertQueryEquals("stop^3", qpAnalyzer, ""); - assertQueryEquals("stop", qpAnalyzer, ""); - assertQueryEquals("(stop)^3", qpAnalyzer, ""); - assertQueryEquals("((stop))^3", qpAnalyzer, ""); - assertQueryEquals("(stop^3)", qpAnalyzer, ""); - assertQueryEquals("((stop)^3)", qpAnalyzer, ""); - assertQueryEquals("(stop)", qpAnalyzer, ""); - assertQueryEquals("((stop))", qpAnalyzer, ""); + assertMatchNoDocsQuery("stop^3", qpAnalyzer); + assertMatchNoDocsQuery("stop", qpAnalyzer); + assertMatchNoDocsQuery("(stop)^3", qpAnalyzer); + assertMatchNoDocsQuery("((stop))^3", qpAnalyzer); + assertMatchNoDocsQuery("(stop^3)", qpAnalyzer); + assertMatchNoDocsQuery("((stop)^3)", qpAnalyzer); + assertMatchNoDocsQuery("(stop)", qpAnalyzer); + assertMatchNoDocsQuery("((stop))", qpAnalyzer); assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery); assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery); } @@ -992,7 +1006,7 @@ public class TestQPHelper extends LuceneTestCase { q = qp2.parse("the^3", "field"); // "the" is a stop word so the result is an empty query: assertNotNull(q); - assertEquals("", q.toString()); + assertMatchNoDocsQuery(q); assertFalse(q instanceof BoostQuery); } diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java index f1eccf467ce..d58f6605670 100644 --- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java +++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java @@ -161,8 +161,7 @@ public abstract class QueryParserTestBase extends LuceneTestCase { return getQuery(query, (Analyzer)null); } - public void assertQueryEquals(String query, Analyzer a, String result) - throws Exception { + public void assertQueryEquals(String query, Analyzer a, String result) throws Exception { Query q = getQuery(query, a); String s = q.toString("field"); if (!s.equals(result)) { @@ -171,6 +170,20 @@ public abstract class QueryParserTestBase extends LuceneTestCase { } } + public void assertMatchNoDocsQuery(String queryString, Analyzer a) throws Exception { + assertMatchNoDocsQuery(getQuery(queryString, a)); + } + + public void assertMatchNoDocsQuery(Query query) throws Exception { + if (query instanceof MatchNoDocsQuery) { + // good + } else if (query instanceof BooleanQuery && ((BooleanQuery) query).clauses().size() == 0) { + // good + } else { + fail("expected MatchNoDocsQuery or an empty BooleanQuery but got: " + query); + } + } + public void assertQueryEquals(CommonQueryParserConfiguration cqpC, String field, String query, String result) throws Exception { Query q = getQuery(query, cqpC); @@ -418,7 +431,7 @@ public abstract class QueryParserTestBase extends LuceneTestCase { public void testNumber() throws Exception { // The numbers go away because SimpleAnalzyer ignores them - assertQueryEquals("3", null, ""); + assertMatchNoDocsQuery("3", null); assertQueryEquals("term 1.0 1 2", null, "term"); assertQueryEquals("term term1 term2", null, "term term term"); @@ -540,14 +553,14 @@ public abstract class QueryParserTestBase extends LuceneTestCase { // "term phrase1 phrase2 term"); assertQueryEquals("term AND NOT phrase term", qpAnalyzer, "+term -(phrase1 phrase2) term"); - assertQueryEquals("stop^3", qpAnalyzer, ""); - assertQueryEquals("stop", qpAnalyzer, ""); - assertQueryEquals("(stop)^3", qpAnalyzer, ""); - assertQueryEquals("((stop))^3", qpAnalyzer, ""); - assertQueryEquals("(stop^3)", qpAnalyzer, ""); - assertQueryEquals("((stop)^3)", qpAnalyzer, ""); - assertQueryEquals("(stop)", qpAnalyzer, ""); - assertQueryEquals("((stop))", qpAnalyzer, ""); + assertMatchNoDocsQuery("stop^3", qpAnalyzer); + assertMatchNoDocsQuery("stop", qpAnalyzer); + assertMatchNoDocsQuery("(stop)^3", qpAnalyzer); + assertMatchNoDocsQuery("((stop))^3", qpAnalyzer); + assertMatchNoDocsQuery("(stop^3)", qpAnalyzer); + assertMatchNoDocsQuery("((stop)^3)", qpAnalyzer); + assertMatchNoDocsQuery("(stop)", qpAnalyzer); + assertMatchNoDocsQuery("((stop))", qpAnalyzer); assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery); assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery); @@ -881,7 +894,7 @@ public abstract class QueryParserTestBase extends LuceneTestCase { q = getQuery("the^3", qp2); // "the" is a stop word so the result is an empty query: assertNotNull(q); - assertEquals("", q.toString()); + assertMatchNoDocsQuery(q); assertFalse(q instanceof BoostQuery); } diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java index 9de9436e3cd..19f80ab453d 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java @@ -191,12 +191,12 @@ public class LatLonPoint extends Field { // and should not drag in extra bogus junk! TODO: should encodeCeil just throw ArithmeticException to be less trappy here? if (minLatitude == 90.0) { // range cannot match as 90.0 can never exist - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("LatLonPoint.newBoxQuery with minLatitude=90.0"); } if (minLongitude == 180.0) { if (maxLongitude == 180.0) { // range cannot match as 180.0 can never exist - return new MatchNoDocsQuery(); + return new MatchNoDocsQuery("LatLonPoint.newBoxQuery with minLongitude=maxLongitude=180.0"); } else if (maxLongitude < minLongitude) { // encodeCeil() with dateline wrapping! minLongitude = -180.0;