diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java index aae21042878..cb828e2d994 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java @@ -305,7 +305,14 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap this.enabledState = timestampFieldMapperMergeWith.enabledState; } } else { - if (!timestampFieldMapperMergeWith.defaultTimestamp().equals(defaultTimestamp)) { + if (timestampFieldMapperMergeWith.defaultTimestamp() == null && defaultTimestamp == null) { + return; + } + if (defaultTimestamp == null) { + mergeContext.addConflict("Cannot update default in _timestamp value. Value is null now encountering " + timestampFieldMapperMergeWith.defaultTimestamp()); + } else if (timestampFieldMapperMergeWith.defaultTimestamp() == null) { + mergeContext.addConflict("Cannot update default in _timestamp value. Value is \" + defaultTimestamp.toString() + \" now encountering null"); + } else if (!timestampFieldMapperMergeWith.defaultTimestamp().equals(defaultTimestamp)) { mergeContext.addConflict("Cannot update default in _timestamp value. Value is " + defaultTimestamp.toString() + " now encountering " + timestampFieldMapperMergeWith.defaultTimestamp()); } if (this.path != null) { diff --git a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java index c15eb8c5cba..b6cda34ea51 100644 --- a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java @@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.timestamp; import org.apache.lucene.index.IndexOptions; import org.elasticsearch.Version; import org.elasticsearch.action.TimestampParsingException; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; @@ -541,6 +542,87 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { } } + /** + * Test case for #9204 + */ + @Test + public void testMergingNullValues() throws Exception { + // From trying to add another field with default = null + String mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", (String) null) + .endObject() + .endObject().endObject().string(); + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + + DocumentMapper docMapper = parser.parse(mapping); + mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", (String) null) + .endObject() + .startObject("properties") + .startObject("foo") + .field("type", "string") + .endObject() + .endObject() + .endObject().endObject().string(); + + DocumentMapper.MergeResult mergeResult = docMapper.merge(parser.parse(mapping), DocumentMapper.MergeFlags.mergeFlags().simulate(true)); + assertThat(mergeResult.hasConflicts(), is(false)); + + client().admin().indices().delete(new DeleteIndexRequest("test")).get(); + + // From trying to update from null to non null + mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", (String) null) + .endObject() + .endObject().endObject().string(); + parser = createIndex("test").mapperService().documentMapperParser(); + + docMapper = parser.parse(mapping); + mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", "now") + .endObject() + .endObject().endObject().string(); + + mergeResult = docMapper.merge(parser.parse(mapping), DocumentMapper.MergeFlags.mergeFlags().simulate(true)); + assertThat(mergeResult.hasConflicts(), is(true)); + + client().admin().indices().delete(new DeleteIndexRequest("test")).get(); + + // From trying to update from non null to null + mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", "now") + .endObject() + .endObject().endObject().string(); + parser = createIndex("test").mapperService().documentMapperParser(); + + docMapper = parser.parse(mapping); + mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", true) + .field("default", (String) null) + .endObject() + .endObject().endObject().string(); + + mergeResult = docMapper.merge(parser.parse(mapping), DocumentMapper.MergeFlags.mergeFlags().simulate(true)); + assertThat(mergeResult.hasConflicts(), is(true)); + } + @Test public void testMergePaths() throws Exception { String[] possiblePathValues = {"some_path", "anotherPath", null};