Skip to content

Commit 32439f4

Browse files
authored
Fix true/false accumulation bug in boolean source fallback (#90895)
The SourceValueFetcherSortedBooleanDocValues previously accumulated true/false value totals without resetting between documents. This means that any counts on the same segment would continue to increase true/false value totals over multiple documents. This change fixes that bug by resetting true/false value totals per document.
1 parent 390003d commit 32439f4

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

docs/changelog/90895.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 90895
2+
summary: Fix true/false accumulation bug in boolean source fallback
3+
area: Infra/Scripting
4+
type: bug
5+
issues: []

server/src/main/java/org/elasticsearch/index/fielddata/SourceValueFetcherSortedBooleanIndexFieldData.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public DocValuesScriptFieldFactory getScriptFieldFactory(String name) {
8181
}
8282
}
8383

84-
private static class SourceValueFetcherSortedBooleanDocValues extends SortedNumericDocValues implements ValueFetcherDocValues {
84+
static class SourceValueFetcherSortedBooleanDocValues extends SortedNumericDocValues implements ValueFetcherDocValues {
8585

8686
private final LeafReaderContext leafReaderContext;
8787

@@ -92,7 +92,7 @@ private static class SourceValueFetcherSortedBooleanDocValues extends SortedNume
9292
private int falseCount;
9393
private int iteratorIndex;
9494

95-
private SourceValueFetcherSortedBooleanDocValues(
95+
SourceValueFetcherSortedBooleanDocValues(
9696
LeafReaderContext leafReaderContext,
9797
ValueFetcher valueFetcher,
9898
SourceLookup sourceLookup
@@ -106,6 +106,9 @@ private SourceValueFetcherSortedBooleanDocValues(
106106
public boolean advanceExact(int doc) throws IOException {
107107
sourceLookup.setSegmentAndDocument(leafReaderContext, doc);
108108

109+
trueCount = 0;
110+
falseCount = 0;
111+
109112
for (Object value : valueFetcher.fetchValues(sourceLookup, doc, Collections.emptyList())) {
110113
assert value instanceof Boolean;
111114
if ((Boolean) value) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.index.fielddata;
10+
11+
import org.apache.lucene.index.LeafReaderContext;
12+
import org.elasticsearch.index.fielddata.SourceValueFetcherSortedBooleanIndexFieldData.SourceValueFetcherSortedBooleanDocValues;
13+
import org.elasticsearch.search.lookup.SourceLookup;
14+
import org.elasticsearch.test.ESTestCase;
15+
16+
import java.io.IOException;
17+
import java.util.List;
18+
19+
public class SourceValueFetcherIndexFieldDataTests extends ESTestCase {
20+
21+
public void testSourceValueFetcherSortedBooleanDocValues() throws IOException {
22+
List<List<Object>> docs = List.of(
23+
List.of(randomBoolean()),
24+
List.of(randomBoolean(), randomBoolean()),
25+
List.of(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()),
26+
List.of(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean())
27+
);
28+
29+
SourceValueFetcherSortedBooleanDocValues values = new SourceValueFetcherSortedBooleanDocValues(
30+
null,
31+
(source, doc, ignoredValues) -> docs.get(doc),
32+
new SourceLookup(null) {
33+
@Override
34+
public void setSegmentAndDocument(LeafReaderContext context, int docId) {
35+
// do nothing
36+
}
37+
}
38+
);
39+
40+
for (int doc = 0; doc < docs.size(); ++doc) {
41+
values.advanceExact(doc);
42+
43+
int docTrues = 0;
44+
int docFalses = 0;
45+
46+
for (Object object : docs.get(doc)) {
47+
if ((boolean) object) {
48+
++docTrues;
49+
} else {
50+
++docFalses;
51+
}
52+
}
53+
54+
assertEquals(docs.get(doc).size(), values.docValueCount());
55+
56+
int valueTrues = 0;
57+
int valueFalses = 0;
58+
59+
for (int count = 0; count < values.docValueCount(); ++count) {
60+
long value = values.nextValue();
61+
62+
if (value == 1L) {
63+
++valueTrues;
64+
} else if (value == 0L) {
65+
++valueFalses;
66+
} else {
67+
throw new IllegalStateException("expected 0L or 1L for boolean value, found [" + value + "]");
68+
}
69+
}
70+
71+
assertEquals(docTrues, valueTrues);
72+
assertEquals(docFalses, valueFalses);
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)