You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dn...@apache.org on 2026/07/14 23:18:47 UTC
(lucene) 01/01: Handle inconsistent schema on flush with index sorts (#15125)
This is an automated email from the ASF dual-hosted git repository.
dnhatn pushed a commit to branch 10_5_backport_15125
in repository https://gitbox.apache.org/repos/asf/lucene.git
commit 0fec5b6a292404f0d46ba4da983399e63d50ff6e
Author: Nhat Nguyen <nh...@elastic.co>
AuthorDate: Mon Sep 29 10:05:29 2025 -0700
Handle inconsistent schema on flush with index sorts (#15125)
If index sorts are configured and a document's schema is inconsistent
with existing segments, IndexWriter may encounter a NullPointerException
when building sort comparators.
---
lucene/CHANGES.txt | 2 +-
.../org/apache/lucene/index/IndexingChain.java | 10 ++--
.../org/apache/lucene/index/TestIndexSorting.java | 63 ++++++++++++++++++++++
3 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 11580688c04..01ccbf80678 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -7,7 +7,7 @@ http://s.apache.org/luceneversions
Bug Fixes
---------------------
-(No changes)
+* GITHUB#15125: Handle inconsistent schema on flush with index sorts (Nhat Nguyen)
======================= Lucene 10.5.0 =======================
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java b/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java
index 02f6580f9c1..8de567704a3 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java
@@ -181,7 +181,7 @@ final class IndexingChain implements Accountable {
@Override
public NumericDocValues getNumericDocValues(String field) {
PerField pf = getPerField(field);
- if (pf == null) {
+ if (pf == null || pf.fieldInfo == null) {
return null;
}
if (pf.fieldInfo.getDocValuesType() == DocValuesType.NUMERIC) {
@@ -193,7 +193,7 @@ final class IndexingChain implements Accountable {
@Override
public BinaryDocValues getBinaryDocValues(String field) {
PerField pf = getPerField(field);
- if (pf == null) {
+ if (pf == null || pf.fieldInfo == null) {
return null;
}
if (pf.fieldInfo.getDocValuesType() == DocValuesType.BINARY) {
@@ -205,7 +205,7 @@ final class IndexingChain implements Accountable {
@Override
public SortedDocValues getSortedDocValues(String field) throws IOException {
PerField pf = getPerField(field);
- if (pf == null) {
+ if (pf == null || pf.fieldInfo == null) {
return null;
}
if (pf.fieldInfo.getDocValuesType() == DocValuesType.SORTED) {
@@ -217,7 +217,7 @@ final class IndexingChain implements Accountable {
@Override
public SortedNumericDocValues getSortedNumericDocValues(String field) throws IOException {
PerField pf = getPerField(field);
- if (pf == null) {
+ if (pf == null || pf.fieldInfo == null) {
return null;
}
if (pf.fieldInfo.getDocValuesType() == DocValuesType.SORTED_NUMERIC) {
@@ -229,7 +229,7 @@ final class IndexingChain implements Accountable {
@Override
public SortedSetDocValues getSortedSetDocValues(String field) throws IOException {
PerField pf = getPerField(field);
- if (pf == null) {
+ if (pf == null || pf.fieldInfo == null) {
return null;
}
if (pf.fieldInfo.getDocValuesType() == DocValuesType.SORTED_SET) {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java
index f174fba07a9..fff8623e3f7 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java
@@ -54,6 +54,8 @@ import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.FloatDocValuesField;
import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.KeywordField;
+import org.apache.lucene.document.LongField;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.document.SortedNumericDocValuesField;
@@ -3478,4 +3480,65 @@ public class TestIndexSorting extends LuceneTestCase {
}
}
}
+
+ public void testFlushAfterInconsistentSchema() throws IOException {
+ IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random()));
+ if (random().nextBoolean()) {
+ Sort indexSort = new Sort(new SortField("host.name", SortField.Type.STRING));
+ iwc.setIndexSort(indexSort);
+ }
+ try (Directory dir = newDirectory();
+ IndexWriter w = new IndexWriter(dir, iwc)) {
+ Consumer<Document> addExtraFields =
+ doc -> {
+ int extraFields = random().nextInt(100);
+ for (int i = 0; i < extraFields; i++) {
+ if (random().nextBoolean()) {
+ doc.add(new NumericDocValuesField("extra-dv-" + i, i));
+ }
+ if (random().nextBoolean()) {
+ doc.add(new LongField("extra-point-" + i, i, Store.NO));
+ }
+ if (random().nextBoolean()) {
+ doc.add(
+ new KeywordField(
+ "extra-posting-" + i, new BytesRef(Integer.toString(i)), Store.NO));
+ }
+ }
+ };
+ // first segment
+ {
+ Document doc = new Document();
+ doc.add(new SortedDocValuesField("host.name", newBytesRef("h2")));
+ doc.add(new LongField("@timestamp", 1, Store.NO));
+ addExtraFields.accept(doc);
+ w.addDocument(doc);
+ w.commit();
+ }
+ // second segment
+ {
+ var doc = new Document();
+ doc.add(new NumericDocValuesField("@timestamp", 2));
+ addExtraFields.accept(doc);
+ doc.add(new SortedDocValuesField("host.name", newBytesRef("h1")));
+ expectThrows(IllegalArgumentException.class, () -> w.addDocument(doc));
+ w.commit();
+ }
+ try (DirectoryReader reader = DirectoryReader.open(w)) {
+ assertEquals(1, reader.numDocs());
+ }
+ // third segment
+ {
+ var doc = new Document();
+ addExtraFields.accept(doc);
+ doc.add(new LongField("@timestamp", 3, Store.NO));
+ doc.add(new SortedDocValuesField("host.name", newBytesRef("h1")));
+ w.addDocument(doc);
+ w.commit();
+ }
+ try (DirectoryReader reader = DirectoryReader.open(w)) {
+ assertEquals(2, reader.numDocs());
+ }
+ }
+ }
}