From a295b0aa86fba667259440c211e125276121d70c Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Mon, 7 Sep 2020 10:58:18 +0100 Subject: [PATCH] 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. --- .../index/mapper/DateFieldMapper.java | 6 ++--- .../index/mapper/DateFieldMapperTests.java | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java index d2046c32f61..a195eab3fb3 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java @@ -235,12 +235,12 @@ public final class DateFieldMapper extends ParametrizedFieldMapper { 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) { return null; } try { - return formatter.parseMillis(nullValue.getValue()); + return fieldType.parse(nullValue.getValue()); } catch (Exception 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(), buildFormatter(), resolution, meta.getValue()); ft.setBoost(boost.getValue()); - Long nullTimestamp = parseNullValue(ft.dateTimeFormatter); + Long nullTimestamp = parseNullValue(ft); return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), nullTimestamp, resolution, indexCreatedVersion, this); } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java index adcf0d0e0a8..20317a52c2a 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java @@ -193,6 +193,33 @@ public class DateFieldMapperTests extends MapperTestCase { 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() { MapperParsingException e = expectThrows(MapperParsingException.class,