Improve error messages on bad [format] and [null_value] params for date mapper (#61932)

Currently, if an incorrectly formatted date is passed as a null_value for a date field mapper
configuration, you get a vague error:

Failed to parse mapping [_doc]: cannot parse empty date
Similarly, if you pass an incorrect format, you get the error:

Failed to parse mapping [_doc]: Invalid format [...]
This commit improves both these errors by including the mapper name and parameter that
are misconfigured.

Fixes #61712
This commit is contained in:
Alan Woodward 2020-09-04 14:02:18 +01:00 committed by Alan Woodward
parent 289b1f4ae7
commit 66bb1eea98
2 changed files with 35 additions and 10 deletions

View File

@ -217,15 +217,16 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
}
}
protected DateFieldType setupFieldType(BuilderContext context) {
DateFormatter formatter;
if (Joda.isJodaPattern(indexCreatedVersion, format.getValue())) {
formatter = Joda.forPattern(format.getValue()).withLocale(locale.getValue());
} else {
formatter = DateFormatter.forPattern(format.getValue()).withLocale(locale.getValue());
private DateFormatter buildFormatter() {
try {
if (Joda.isJodaPattern(indexCreatedVersion, format.getValue())) {
return Joda.forPattern(format.getValue()).withLocale(locale.getValue());
} else {
return DateFormatter.forPattern(format.getValue()).withLocale(locale.getValue());
}
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Error parsing [format] on field [" + name() + "]: " + e.getMessage(), e);
}
return new DateFieldType(buildFullName(context), index.getValue(), docValues.getValue(),
formatter, resolution, meta.getValue());
}
@Override
@ -233,11 +234,24 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
return Arrays.asList(index, docValues, store, format, locale, nullValue, ignoreMalformed, boost, meta);
}
private Long parseNullValue(DateFormatter formatter) {
if (nullValue.getValue() == null) {
return null;
}
try {
return formatter.parseMillis(nullValue.getValue());
}
catch (Exception e) {
throw new MapperParsingException("Error parsing [null_value] on field [" + name() + "]: " + e.getMessage(), e);
}
}
@Override
public DateFieldMapper build(BuilderContext context) {
DateFieldType ft = setupFieldType(context);
DateFieldType ft = new DateFieldType(buildFullName(context), index.getValue(), docValues.getValue(),
buildFormatter(), resolution, meta.getValue());
ft.setBoost(boost.getValue());
Long nullTimestamp = nullValue.getValue() == null ? null : ft.dateTimeFormatter.parseMillis(nullValue.getValue());
Long nullTimestamp = parseNullValue(ft.dateTimeFormatter);
return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context),
copyTo.build(), nullTimestamp, resolution, indexCreatedVersion, this);
}

View File

@ -39,6 +39,7 @@ import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
public class DateFieldMapperTests extends MapperTestCase {
@ -192,6 +193,15 @@ public class DateFieldMapperTests extends MapperTestCase {
assertFalse(dvField.fieldType().stored());
}
public void testBadNullValue() {
MapperParsingException e = expectThrows(MapperParsingException.class,
() -> createDocumentMapper(fieldMapping(b -> b.field("type", "date").field("null_value", ""))));
assertThat(e.getMessage(),
equalTo("Failed to parse mapping [_doc]: Error parsing [null_value] on field [field]: cannot parse empty date"));
}
public void testNullConfigValuesFail() {
Exception e = expectThrows(MapperParsingException.class,
() -> createDocumentMapper(fieldMapping(b -> b.field("type", "date").nullField("format"))));
@ -244,6 +254,7 @@ public class DateFieldMapperTests extends MapperTestCase {
.field("type", "date")
.field("format", "test_format"))));
assertThat(e.getMessage(), containsString("Invalid format: [test_format]: Unknown pattern letter: t"));
assertThat(e.getMessage(), containsString("Error parsing [format] on field [field]: Invalid"));
}
public void testFetchSourceValue() {