SQL: Fix merging of incompatible multi-fields (#39560)

Fix bug in IndexResolver that caused conflicts in multi-field types to
be ignored up (causing the query to fail later on due to mapping
conflicts).
The issue was caused by the multi-field which forced the parent creation
before checking its validity across mappings

Fix #39547

(cherry picked from commit 4e4fe289f90b9b5eae09072d54903701a3128696)
This commit is contained in:
Costin Leau 2019-03-02 10:29:48 +02:00 committed by Costin Leau
parent dfe81b260e
commit e038ccef13
2 changed files with 45 additions and 1 deletions

View File

@ -324,7 +324,9 @@ public class IndexResolver {
// if the name wasn't added before
final InvalidMappedField invalidF = invalidField;
final FieldCapabilities fieldCapab = fieldCap;
if (!flattedMapping.containsKey(name)) {
EsField esField = flattedMapping.get(name);
if (esField == null || (invalidF != null && (esField instanceof InvalidMappedField) == false)) {
createField(name, fieldCaps, hierarchicalMapping, flattedMapping, s -> {
return invalidF != null ? invalidF : createField(s, fieldCapab.getType(), emptyMap(), fieldCapab.isAggregatable());
});

View File

@ -133,6 +133,48 @@ public class IndexResolverTests extends ESTestCase {
assertEquals(DataType.KEYWORD, esIndex.mapping().get("text").getDataType());
}
public void testMergeIncompatibleCapabilitiesOfObjectFields() throws Exception {
Map<String, Map<String, FieldCapabilities>> fieldCaps = new HashMap<>();
int depth = randomInt(5);
List<String> level = new ArrayList<>();
String fieldName = randomAlphaOfLength(3);
level.add(fieldName);
for (int i = 0; i <= depth; i++) {
String l = randomAlphaOfLength(3);
level.add(l);
fieldName += "." + l;
}
// define a sub-field
addFieldCaps(fieldCaps, fieldName + ".keyword", "keyword", true, true);
Map<String, FieldCapabilities> multi = new HashMap<>();
multi.put("long", new FieldCapabilities(fieldName, "long", true, true, new String[] { "one-index" }, null, null));
multi.put("text", new FieldCapabilities(fieldName, "text", true, false, new String[] { "another-index" }, null, null));
fieldCaps.put(fieldName, multi);
String wildcard = "*";
IndexResolution resolution = IndexResolver.mergedMapping(wildcard, fieldCaps);
assertTrue(resolution.isValid());
EsIndex esIndex = resolution.get();
assertEquals(wildcard, esIndex.name());
EsField esField = null;
Map<String, EsField> props = esIndex.mapping();
for (String lvl : level) {
esField = props.get(lvl);
props = esField.getProperties();
}
assertEquals(InvalidMappedField.class, esField.getClass());
assertEquals("mapped as [2] incompatible types: [text] in [another-index], [long] in [one-index]",
((InvalidMappedField) esField).errorMessage());
}
public static IndexResolution merge(EsIndex... indices) {
return IndexResolver.mergedMapping("*", fromMappings(indices));
}