You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ti...@apache.org on 2026/06/13 19:32:22 UTC

(lucene) branch branch_10x updated: Allow frozen FieldType to cache again after new FT (#16171)

This is an automated email from the ASF dual-hosted git repository.

Tim-Brooks pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git


The following commit(s) were added to refs/heads/branch_10x by this push:
     new eccb3394382 Allow frozen FieldType to cache again after new FT (#16171)
eccb3394382 is described below

commit eccb3394382d4a9f05c138a26911157f5b9d29df
Author: neoReMinD <xu...@gmail.com>
AuthorDate: Sun Jun 14 03:26:38 2026 +0800

    Allow frozen FieldType to cache again after new FT (#16171)
    
    Allow cache to re-promote after type switch between compatible frozen
    FieldType instances, avoid revalidating schema. Add test for
    multiValueForcesDeoptimize coverage.
---
 lucene/CHANGES.txt                                 |  2 ++
 .../org/apache/lucene/index/IndexingChain.java     |  9 ++----
 .../org/apache/lucene/index/TestIndexOptions.java  | 36 ++++++++++++++++++++++
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 60406d2e946..a888fa5af41 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -243,6 +243,8 @@ Optimizations
 
 * GITHUB#16166: Add bulk range evaluation for multi-valued sorted numeric doc values. (Costin Leau)
 
+* GITHUB#16171: Address frozen FieldType cache never recovering after type switch. (neoremind)
+
 Bug Fixes
 ---------------------
 * GITHUB#15754: Fix HTMLStripCharFilter to prevent tags from incorrectly consuming subsequent
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 8eeffedcccb..5284845919c 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java
@@ -693,10 +693,10 @@ final class IndexingChain implements Accountable {
       PerField pf = fields[i];
       if (pf.fieldInfo == null) {
         initializeFieldInfo(pf);
-        pf.trySetValidatedFrozenFieldType();
       } else {
         pf.schema.assertSameSchema(pf.fieldInfo);
       }
+      pf.trySetValidatedFrozenFieldType();
     }
   }
 
@@ -1777,12 +1777,7 @@ final class IndexingChain implements Accountable {
 
     void reset(int docId, IndexableFieldType fieldType) {
       first = true;
-      if (fieldInfo == null) {
-        // The first time we encounter this field in a segment propose a frozen field to optimize
-        // the validation step. This will be promoted in trySetValidatedFrozenFieldType if it is
-        // frozen and valid.
-        candidateFieldType = fieldType;
-      }
+      candidateFieldType = fieldType;
       if (fieldType == validatedFrozenFieldType) {
         schema.resetJustDocId(docId);
       } else {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexOptions.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexOptions.java
index 5fed25d5523..3c360ac4d8e 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexOptions.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexOptions.java
@@ -235,6 +235,7 @@ public class TestIndexOptions extends LuceneTestCase {
     Document doc = new Document();
     doc.add(new Field("foo", "bar1", frozenFt));
     doc.add(new Field("foo", "bar2", differentFt));
+    // throw exception because of intra-document inconsistency
     IllegalArgumentException e =
         expectThrows(IllegalArgumentException.class, () -> w.addDocument(doc));
     assertTrue(e.getMessage(), e.getMessage().contains("index options"));
@@ -331,6 +332,41 @@ public class TestIndexOptions extends LuceneTestCase {
     dir.close();
   }
 
+  public void testMultiValueForcesDeoptimization() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
+    FieldType ftA = new FieldType(TextField.TYPE_STORED);
+    ftA.freeze();
+    FieldType ftB = new FieldType(TextField.TYPE_STORED); // same schema, different instance
+    ftB.freeze();
+    // Doc 0
+    w.addDocument(Collections.singleton(new Field("foo", "val0", ftA)));
+    // Doc 1
+    Document doc = new Document();
+    doc.add(new Field("foo", "val1a", ftA));
+    doc.add(new Field("foo", "val1b", ftB));
+    w.addDocument(doc);
+    // Doc 2
+    w.addDocument(Collections.singleton(new Field("foo", "val2", ftB)));
+    // Doc 3
+    w.addDocument(Collections.singleton(new Field("foo", "val3", ftB)));
+    try (LeafReader r = getOnlyLeafReader(DirectoryReader.open(w))) {
+      assertEquals(4, r.maxDoc());
+    }
+    // Doc 4: multi-valued with incompatible frozen type — must fail
+    FieldType ftC = new FieldType(TextField.TYPE_STORED);
+    ftC.setStoreTermVectors(true);
+    ftC.freeze();
+    Document doc4 = new Document();
+    doc4.add(new Field("foo", "val4a", ftB));
+    doc4.add(new Field("foo", "val4b", ftC));
+    IllegalArgumentException e =
+        expectThrows(IllegalArgumentException.class, () -> w.addDocument(doc4));
+    assertTrue(e.getMessage(), e.getMessage().contains("store term vector"));
+    w.close();
+    dir.close();
+  }
+
   public void testFrozenFieldTypeInDocumentBlock() throws IOException {
     Directory dir = newDirectory();
     IndexWriterConfig iwc = newIndexWriterConfig();