Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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:
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.lucene.index.Terms;
import org.apache.lucene.search.AcceptDocs;
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;
Expand Down Expand Up @@ -84,38 +85,44 @@ 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 {
if (reader instanceof CompositeReader) {
return new SlowCompositeReaderWrapper((CompositeReader) reader);
public static LeafReader wrap(IndexReader reader) {
if (reader instanceof CompositeReader compositeReader) {
return new SlowCompositeReaderWrapper(compositeReader);
} else {
assert reader instanceof LeafReader;
return (LeafReader) reader;
}
}

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().minVersion();
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.minVersion();
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.getFirst().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.sort() : null;
metaData =
new LeafMetaData(
leafMetaData.createdVersionMajor(),
minVersion,
leafMetaData.sort(),
leafMetaData.hasBlocks());
new LeafMetaData(firstLeafMetaData.createdVersionMajor(), minVersion, sort, hasBlocks);
}
fieldInfos = FieldInfos.getMergedFieldInfos(in);
}
Expand Down
Loading