mirror of https://github.com/apache/lucene.git
Guard FieldExistsQuery against null pointers (#11794)
FieldExistsQuery checks if there are points for a certain field, and then retrieves the corresponding point values. When all documents that had points for a certain field have been deleted from a certain segments, as well as merged away, field info may report that there are points yet the corresponding point values are null. With this change we add a null check in FieldExistsQuery. Long term, we will likely want to prevent this situation from happening. Relates #11393
This commit is contained in:
parent
6c46662b43
commit
4eaebee686
|
@ -169,6 +169,8 @@ Bug Fixes
|
|||
|
||||
* LUCENE-10674: Ensure BitSetConjDISI returns NO_MORE_DOCS when sub-iterator exhausts. (Jack Mazanec)
|
||||
|
||||
* GITHUB#11794: Guard FieldExistsQuery against null pointers (Luca Cavanna)
|
||||
|
||||
Build
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -230,9 +230,11 @@ public class FieldExistsQuery extends Query {
|
|||
!= DocValuesType.NONE) { // the field indexes doc values
|
||||
if (reader.hasDeletions() == false) {
|
||||
if (fieldInfo.getPointDimensionCount() > 0) {
|
||||
return reader.getPointValues(field).getDocCount();
|
||||
PointValues pointValues = reader.getPointValues(field);
|
||||
return pointValues == null ? 0 : pointValues.getDocCount();
|
||||
} else if (fieldInfo.getIndexOptions() != IndexOptions.NONE) {
|
||||
return reader.terms(field).getDocCount();
|
||||
Terms terms = reader.terms(field);
|
||||
return terms == null ? 0 : terms.getDocCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -702,6 +702,64 @@ public class TestFieldExistsQuery extends LuceneTestCase {
|
|||
return v;
|
||||
}
|
||||
|
||||
public void testDeleteAllPointDocs() throws Exception {
|
||||
try (Directory dir = newDirectory();
|
||||
RandomIndexWriter iw = new RandomIndexWriter(random(), dir)) {
|
||||
|
||||
Document doc = new Document();
|
||||
doc.add(new StringField("id", "0", Field.Store.NO));
|
||||
doc.add(new LongPoint("long", 17));
|
||||
doc.add(new NumericDocValuesField("long", 17));
|
||||
iw.addDocument(doc);
|
||||
// add another document before the flush, otherwise the segment only has the document that
|
||||
// we are going to delete and the merge simply ignores the segment without carrying over its
|
||||
// field infos
|
||||
iw.addDocument(new Document());
|
||||
// make sure there are two segments or force merge will be a no-op
|
||||
iw.flush();
|
||||
iw.addDocument(new Document());
|
||||
iw.commit();
|
||||
|
||||
iw.deleteDocuments(new Term("id", "0"));
|
||||
iw.forceMerge(1);
|
||||
|
||||
try (IndexReader reader = iw.getReader()) {
|
||||
assertTrue(reader.leaves().size() == 1 && reader.hasDeletions() == false);
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(0, searcher.count(new FieldExistsQuery("long")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteAllTermDocs() throws Exception {
|
||||
try (Directory dir = newDirectory();
|
||||
RandomIndexWriter iw = new RandomIndexWriter(random(), dir)) {
|
||||
|
||||
Document doc = new Document();
|
||||
doc.add(new StringField("id", "0", Field.Store.NO));
|
||||
doc.add(new StringField("str", "foo", Store.NO));
|
||||
doc.add(new SortedDocValuesField("str", new BytesRef("foo")));
|
||||
iw.addDocument(doc);
|
||||
// add another document before the flush, otherwise the segment only has the document that
|
||||
// we are going to delete and the merge simply ignores the segment without carrying over its
|
||||
// field infos
|
||||
iw.addDocument(new Document());
|
||||
// make sure there are two segments or force merge will be a no-op
|
||||
iw.flush();
|
||||
iw.addDocument(new Document());
|
||||
iw.commit();
|
||||
|
||||
iw.deleteDocuments(new Term("id", "0"));
|
||||
iw.forceMerge(1);
|
||||
|
||||
try (IndexReader reader = iw.getReader()) {
|
||||
assertTrue(reader.leaves().size() == 1 && reader.hasDeletions() == false);
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(0, searcher.count(new FieldExistsQuery("str")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSameMatches(IndexSearcher searcher, Query q1, Query q2, boolean scores)
|
||||
throws IOException {
|
||||
final int maxDoc = searcher.getIndexReader().maxDoc();
|
||||
|
|
Loading…
Reference in New Issue