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)
|
* LUCENE-10674: Ensure BitSetConjDISI returns NO_MORE_DOCS when sub-iterator exhausts. (Jack Mazanec)
|
||||||
|
|
||||||
|
* GITHUB#11794: Guard FieldExistsQuery against null pointers (Luca Cavanna)
|
||||||
|
|
||||||
Build
|
Build
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -230,9 +230,11 @@ public class FieldExistsQuery extends Query {
|
||||||
!= DocValuesType.NONE) { // the field indexes doc values
|
!= DocValuesType.NONE) { // the field indexes doc values
|
||||||
if (reader.hasDeletions() == false) {
|
if (reader.hasDeletions() == false) {
|
||||||
if (fieldInfo.getPointDimensionCount() > 0) {
|
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) {
|
} 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;
|
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)
|
private void assertSameMatches(IndexSearcher searcher, Query q1, Query q2, boolean scores)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final int maxDoc = searcher.getIndexReader().maxDoc();
|
final int maxDoc = searcher.getIndexReader().maxDoc();
|
||||||
|
|
Loading…
Reference in New Issue