Fix null_value parsing for data_nanos field mapper (#61994)

The null_value parameter for date fields is always parsed using DateFormatter.parseMillis,
which is incorrect for nanosecond resolution fields. This commit changes the parsing logic
to always use DateFieldType.parse() to parse the null value.
This commit is contained in:
Alan Woodward 2020-09-07 10:58:18 +01:00 committed by Alan Woodward
parent 1799c0c583
commit a295b0aa86
2 changed files with 30 additions and 3 deletions

View File

@ -235,12 +235,12 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
return Arrays.asList(index, docValues, store, format, locale, nullValue, ignoreMalformed, boost, meta); return Arrays.asList(index, docValues, store, format, locale, nullValue, ignoreMalformed, boost, meta);
} }
private Long parseNullValue(DateFormatter formatter) { private Long parseNullValue(DateFieldType fieldType) {
if (nullValue.getValue() == null) { if (nullValue.getValue() == null) {
return null; return null;
} }
try { try {
return formatter.parseMillis(nullValue.getValue()); return fieldType.parse(nullValue.getValue());
} }
catch (Exception e) { catch (Exception e) {
throw new MapperParsingException("Error parsing [null_value] on field [" + name() + "]: " + e.getMessage(), e); throw new MapperParsingException("Error parsing [null_value] on field [" + name() + "]: " + e.getMessage(), e);
@ -252,7 +252,7 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
DateFieldType ft = new DateFieldType(buildFullName(context), index.getValue(), docValues.getValue(), DateFieldType ft = new DateFieldType(buildFullName(context), index.getValue(), docValues.getValue(),
buildFormatter(), resolution, meta.getValue()); buildFormatter(), resolution, meta.getValue());
ft.setBoost(boost.getValue()); ft.setBoost(boost.getValue());
Long nullTimestamp = parseNullValue(ft.dateTimeFormatter); Long nullTimestamp = parseNullValue(ft);
return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context), return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context),
copyTo.build(), nullTimestamp, resolution, indexCreatedVersion, this); copyTo.build(), nullTimestamp, resolution, indexCreatedVersion, this);
} }

View File

@ -193,6 +193,33 @@ public class DateFieldMapperTests extends MapperTestCase {
assertFalse(dvField.fieldType().stored()); assertFalse(dvField.fieldType().stored());
} }
public void testNanosNullValue() throws IOException {
DocumentMapper mapper = createDocumentMapper(fieldMapping(this::minimalMapping));
ParsedDocument doc = mapper.parse(source(b -> b.nullField("field")));
assertArrayEquals(new IndexableField[0], doc.rootDoc().getFields("field"));
MapperService mapperService = createMapperService(fieldMapping(b -> b
.field("type", "date_nanos")
.field("null_value", "2016-03-11")));
DateFieldMapper.DateFieldType ft = (DateFieldMapper.DateFieldType) mapperService.fieldType("field");
long expectedNullValue = ft.parse("2016-03-11");
doc = mapperService.documentMapper().parse(source(b -> b.nullField("field")));
IndexableField[] fields = doc.rootDoc().getFields("field");
assertEquals(2, fields.length);
IndexableField pointField = fields[0];
assertEquals(1, pointField.fieldType().pointIndexDimensionCount());
assertEquals(8, pointField.fieldType().pointNumBytes());
assertFalse(pointField.fieldType().stored());
assertEquals(expectedNullValue, pointField.numericValue().longValue());
IndexableField dvField = fields[1];
assertEquals(DocValuesType.SORTED_NUMERIC, dvField.fieldType().docValuesType());
assertEquals(expectedNullValue, dvField.numericValue().longValue());
assertFalse(dvField.fieldType().stored());
}
public void testBadNullValue() { public void testBadNullValue() {
MapperParsingException e = expectThrows(MapperParsingException.class, MapperParsingException e = expectThrows(MapperParsingException.class,