LUCENE-8082: Fix NPE in TopFieldCollectors that don't track total hit count

This commit is contained in:
Jim Ferenczi 2017-12-07 14:08:46 +01:00
parent 4fc5a872de
commit 68d16c2a65
2 changed files with 34 additions and 3 deletions

View File

@ -121,9 +121,11 @@ public abstract class TopFieldCollector extends TopDocsCollector<Entry> {
final LeafFieldComparator[] comparators = queue.getComparators(context); final LeafFieldComparator[] comparators = queue.getComparators(context);
final int[] reverseMul = queue.getReverseMul(); final int[] reverseMul = queue.getReverseMul();
final Sort indexSort = context.reader().getMetaData().getSort();
final boolean canEarlyTerminate = trackTotalHits == false && final boolean canEarlyTerminate = trackTotalHits == false &&
trackMaxScore == false && trackMaxScore == false &&
canEarlyTerminate(sort, context.reader().getMetaData().getSort()); indexSort != null &&
canEarlyTerminate(sort, indexSort);
final int initialTotalHits = totalHits; final int initialTotalHits = totalHits;
return new MultiComparatorLeafCollector(comparators, reverseMul, mayNeedScoresTwice) { return new MultiComparatorLeafCollector(comparators, reverseMul, mayNeedScoresTwice) {
@ -212,7 +214,9 @@ public abstract class TopFieldCollector extends TopDocsCollector<Entry> {
this.trackTotalHits = trackTotalHits; this.trackTotalHits = trackTotalHits;
// Must set maxScore to NEG_INF, or otherwise Math.max always returns NaN. // Must set maxScore to NEG_INF, or otherwise Math.max always returns NaN.
maxScore = Float.NEGATIVE_INFINITY; if (trackMaxScore) {
maxScore = Float.NEGATIVE_INFINITY;
}
FieldComparator<?>[] comparators = queue.comparators; FieldComparator<?>[] comparators = queue.comparators;
// Tell all comparators their top value: // Tell all comparators their top value:
@ -227,9 +231,11 @@ public abstract class TopFieldCollector extends TopDocsCollector<Entry> {
public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException { public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException {
docBase = context.docBase; docBase = context.docBase;
final int afterDoc = after.doc - docBase; final int afterDoc = after.doc - docBase;
final Sort indexSort = context.reader().getMetaData().getSort();
final boolean canEarlyTerminate = trackTotalHits == false && final boolean canEarlyTerminate = trackTotalHits == false &&
trackMaxScore == false && trackMaxScore == false &&
canEarlyTerminate(sort, context.reader().getMetaData().getSort()); indexSort != null &&
canEarlyTerminate(sort, indexSort);
final int initialTotalHits = totalHits; final int initialTotalHits = totalHits;
return new MultiComparatorLeafCollector(queue.getComparators(context), queue.getReverseMul(), mayNeedScoresTwice) { return new MultiComparatorLeafCollector(queue.getComparators(context), queue.getReverseMul(), mayNeedScoresTwice) {

View File

@ -102,6 +102,31 @@ public class TestTopFieldCollector extends LuceneTestCase {
assertTrue(Float.isNaN(td.getMaxScore())); assertTrue(Float.isNaN(td.getMaxScore()));
} }
} }
public void testSortWithoutTotalHitTracking() throws Exception {
Sort sort = new Sort(SortField.FIELD_DOC);
for(int i = 0; i < 2; i++) {
Query q = new MatchAllDocsQuery();
// check that setting trackTotalHits to false does not throw an NPE because
// the index is not sorted
TopDocsCollector<Entry> tdc;
if (i % 2 == 0) {
tdc = TopFieldCollector.create(sort, 10, true, false, false, false);
} else {
FieldDoc fieldDoc = new FieldDoc(1, Float.NaN, new Object[] { 1 });
tdc = TopFieldCollector.create(sort, 10, fieldDoc, true, false, false, false);
}
is.search(q, tdc);
TopDocs td = tdc.topDocs();
ScoreDoc[] sd = td.scoreDocs;
for(int j = 0; j < sd.length; j++) {
assertTrue(Float.isNaN(sd[j].score));
}
assertTrue(Float.isNaN(td.getMaxScore()));
}
}
public void testSortWithScoreNoMaxScoreTracking() throws Exception { public void testSortWithScoreNoMaxScoreTracking() throws Exception {