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

dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git

commit aab1c71f0eca891261b5aed97e882085948596fa
Author: David Smiley <[email protected]>
AuthorDate: Sun Sep 6 00:05:39 2026 -0400

    SlowCompositeReaderWrapper: fix index sort and hasBlocks (#4825)
    
    minor fixes; not seen in a realistic setting.
    
    (cherry picked from commit c78158b9811417543c4f7cdf99faed8d25c5943b)
---
 ...owCompositeReaderWrapper-sort-hasblocks-fix.yml |  6 ++++
 .../solr/index/SlowCompositeReaderWrapper.java     | 39 +++++++++++++---------
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git 
a/changelog/unreleased/SlowCompositeReaderWrapper-sort-hasblocks-fix.yml 
b/changelog/unreleased/SlowCompositeReaderWrapper-sort-hasblocks-fix.yml
new file mode 100644
index 00000000000..c1f98f684cc
--- /dev/null
+++ b/changelog/unreleased/SlowCompositeReaderWrapper-sort-hasblocks-fix.yml
@@ -0,0 +1,6 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: SlowCompositeReaderWrapper no longer misreports the index sort and 
hasBlocks of a multi-segment composite view; both were previously taken from 
the first segment only, which is wrong whenever there is more than one segment.
+type: fixed # added, changed, fixed, deprecated, removed, dependency_update, 
security, other
+authors:
+  - name: David Smiley
+links:
diff --git 
a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java 
b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
index cdfbb181671..30cd59034fd 100644
--- a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
+++ b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
@@ -51,6 +51,7 @@ import org.apache.lucene.index.StoredFields;
 import org.apache.lucene.index.TermVectors;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.search.KnnCollector;
+import org.apache.lucene.search.Sort;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.Version;
 import org.apache.lucene.util.packed.PackedInts;
@@ -84,7 +85,7 @@ public final class SlowCompositeReaderWrapper extends 
LeafReader {
    * This method is sugar for getting an {@link LeafReader} from an {@link 
IndexReader} of any kind.
    * If the reader is already atomic, it is returned unchanged, otherwise 
wrapped by this class.
    */
-  public static LeafReader wrap(IndexReader reader) throws IOException {
+  public static LeafReader wrap(IndexReader reader) {
     if (reader instanceof CompositeReader) {
       return new SlowCompositeReaderWrapper((CompositeReader) reader);
     } else {
@@ -93,29 +94,35 @@ public final class SlowCompositeReaderWrapper extends 
LeafReader {
     }
   }
 
-  SlowCompositeReaderWrapper(CompositeReader reader) throws IOException {
+  SlowCompositeReaderWrapper(CompositeReader reader) {
     in = reader;
     in.registerParentReader(this);
-    if (reader.leaves().isEmpty()) {
+    List<LeafReaderContext> leaves = reader.leaves();
+    if (leaves.isEmpty()) {
       metaData = new LeafMetaData(Version.LATEST.major, Version.LATEST, null, 
false);
     } else {
       Version minVersion = Version.LATEST;
-      for (LeafReaderContext leafReaderContext : reader.leaves()) {
-        Version leafVersion = 
leafReaderContext.reader().getMetaData().getMinVersion();
-        if (leafVersion == null) {
-          minVersion = null;
-          break;
-        } else if (minVersion.onOrAfter(leafVersion)) {
-          minVersion = leafVersion;
+      boolean hasBlocks = false;
+      for (LeafReaderContext leafReaderContext : leaves) {
+        LeafMetaData leafMetaData = leafReaderContext.reader().getMetaData();
+        if (minVersion != null) {
+          Version leafVersion = leafMetaData.getMinVersion();
+          if (leafVersion == null) {
+            minVersion = null;
+          } else if (minVersion.onOrAfter(leafVersion)) {
+            minVersion = leafVersion;
+          }
         }
+        // A block (child/nested docs), once written, is never split across 
segments, so the
+        // composite view has blocks as soon as any one of its segments does.
+        hasBlocks |= leafMetaData.hasBlocks();
       }
-      LeafMetaData leafMetaData = 
reader.leaves().get(0).reader().getMetaData();
+      LeafMetaData firstLeafMetaData = leaves.get(0).reader().getMetaData();
+      // The composite view is only actually sorted in the trivial single-leaf 
case: concatenating
+      // multiple segments does not preserve their shared per-segment sort as 
a sort of the whole.
+      Sort sort = leaves.size() == 1 ? firstLeafMetaData.getSort() : null;
       metaData =
-          new LeafMetaData(
-              leafMetaData.getCreatedVersionMajor(),
-              minVersion,
-              leafMetaData.getSort(),
-              leafMetaData.hasBlocks());
+          new LeafMetaData(firstLeafMetaData.getCreatedVersionMajor(), 
minVersion, sort, hasBlocks);
     }
     fieldInfos = FieldInfos.getMergedFieldInfos(in);
   }

Reply via email to