diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 6709305e6ec..0d310a6f1ac 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -180,6 +180,9 @@ Bug fixes rethrown with more useful information about the problem, omitting the incorrect OutOfMemoryError. (Robert Muir, Uwe Schindler) +* LUCENE-5682: NPE in QueryRescorer when Scorer is null + (Joel Bernstein, Mike McCandless) + Test Framework * LUCENE-5622: Fail tests if they print over the given limit of bytes to diff --git a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java index 8403a99fd17..755c3cd4d8a 100644 --- a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java @@ -85,18 +85,23 @@ public abstract class QueryRescorer extends Rescorer { scorer = weight.scorer(readerContext, null); } - int targetDoc = docID - docBase; - int actualDoc = scorer.docID(); - if (actualDoc < targetDoc) { - actualDoc = scorer.advance(targetDoc); - } + if(scorer != null) { + int targetDoc = docID - docBase; + int actualDoc = scorer.docID(); + if (actualDoc < targetDoc) { + actualDoc = scorer.advance(targetDoc); + } - if (actualDoc == targetDoc) { - // Query did match this doc: - hit.score = combine(hit.score, true, scorer.score()); + if (actualDoc == targetDoc) { + // Query did match this doc: + hit.score = combine(hit.score, true, scorer.score()); + } else { + // Query did not match this doc: + assert actualDoc > targetDoc; + hit.score = combine(hit.score, false, 0.0f); + } } else { // Query did not match this doc: - assert actualDoc > targetDoc; hit.score = combine(hit.score, false, 0.0f); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java index 26b21c4326b..28f78b031dd 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java @@ -107,6 +107,46 @@ public class TestQueryRescorer extends LuceneTestCase { dir.close(); } + // Test LUCENE-5682 + public void testNullScorerTermQuery() throws Exception { + Directory dir = newDirectory(); + RandomIndexWriter w = new RandomIndexWriter(random(), dir); + + Document doc = new Document(); + doc.add(newStringField("id", "0", Field.Store.YES)); + doc.add(newTextField("field", "wizard the the the the the oz", Field.Store.NO)); + w.addDocument(doc); + doc = new Document(); + doc.add(newStringField("id", "1", Field.Store.YES)); + // 1 extra token, but wizard and oz are close; + doc.add(newTextField("field", "wizard oz the the the the the the", Field.Store.NO)); + w.addDocument(doc); + IndexReader r = w.getReader(); + w.shutdown(); + + // Do ordinary BooleanQuery: + BooleanQuery bq = new BooleanQuery(); + bq.add(new TermQuery(new Term("field", "wizard")), Occur.SHOULD); + bq.add(new TermQuery(new Term("field", "oz")), Occur.SHOULD); + IndexSearcher searcher = getSearcher(r); + searcher.setSimilarity(new DefaultSimilarity()); + + TopDocs hits = searcher.search(bq, 10); + assertEquals(2, hits.totalHits); + assertEquals("0", searcher.doc(hits.scoreDocs[0].doc).get("id")); + assertEquals("1", searcher.doc(hits.scoreDocs[1].doc).get("id")); + + // Now, resort using TermQuery on term that does not exist. + TermQuery tq = new TermQuery(new Term("field", "gold")); + TopDocs hits2 = QueryRescorer.rescore(searcher, hits, tq, 2.0, 10); + + // Just testing that null scorer is handled. + assertEquals(2, hits2.totalHits); + + r.close(); + dir.close(); + } + public void testCustomCombine() throws Exception { Directory dir = newDirectory(); RandomIndexWriter w = new RandomIndexWriter(random(), dir);