Skip to content
5 changes: 5 additions & 0 deletions docs/changelog/127525.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 127525
summary: Text field block loader properly handles null values from delegate
area: ES|QL
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,12 @@ public Builder builder(BlockFactory factory, int expectedCount) {
* using whatever
*/
private BlockSourceReader.LeafIteratorLookup blockReaderDisiLookup(BlockLoaderContext blContext) {
if (isSyntheticSource && syntheticSourceDelegate != null) {
// Since we are using synthetic source and a delegate, we can't use this field
// to determine if the delegate has values in the document (f.e. handling of `null` is different
// between text and keyword).
return BlockSourceReader.lookupMatchingAll();
}
if (isIndexed()) {
if (getTextSearchInfo().hasNorms()) {
return BlockSourceReader.lookupFromNorms(name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,8 @@ public static Object expectedValue(Map<String, Object> fieldMapping, Object valu
if (params.syntheticSource() && testContext.forceFallbackSyntheticSource() == false && usingSyntheticSourceDelegate) {
var nullValue = (String) keywordMultiFieldMapping.get("null_value");

// Due to how TextFieldMapper#blockReaderDisiLookup works this is complicated.
// If we are using lookupMatchingAll() then we'll see all docs, generate synthetic source using syntheticSourceDelegate,
// parse it and see null_value inside.
// But if we are using lookupFromNorms() we will skip the document (since the text field itself does not exist).
// Same goes for lookupFromFieldNames().
boolean textFieldIndexed = (boolean) fieldMapping.getOrDefault("index", true);

if (value == null) {
if (textFieldIndexed == false && nullValue != null && nullValue.length() <= (int) ignoreAbove) {
if (nullValue != null && nullValue.length() <= (int) ignoreAbove) {
return new BytesRef(nullValue);
}

Expand All @@ -82,12 +75,6 @@ public static Object expectedValue(Map<String, Object> fieldMapping, Object valu
}

var values = (List<String>) value;

// See note above about TextFieldMapper#blockReaderDisiLookup.
if (textFieldIndexed && values.stream().allMatch(Objects::isNull)) {
return null;
}

var indexed = values.stream()
.map(s -> s == null ? nullValue : s)
.filter(Objects::nonNull)
Expand Down
Loading