Skip to content

Commit aa959e6

Browse files
ES|QL: shorten error messages for UnsupportedAttributes (#111973)
When dealing with index patterns, eg. `FROM logs-*`, some fields can have the same name but different types in different indices. In this case we build an error message like ``` Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types: [ip] in [test1, test2], [keyword] in [test3]" ``` With this PR, in case of many indices involved, we avoid listing them all, but we only list three of them and provide information about how many other indices are affected, eg. ``` Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types: [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6] ``` (see the `and [2] other indices`) Since these error messages are stored in `UnspportedAttributes` and serialized, this PR reduces significantly the size of a serialized execution plan with many type conflicts. Fixes #111964 Related to #111358
1 parent ba8590b commit aa959e6

File tree

4 files changed

+156
-16
lines changed

4 files changed

+156
-16
lines changed

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/InvalidMappedField.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,13 @@ private static String makeErrorMessage(Map<String, Set<String>> typesToIndices)
130130
errorMessage.append("[");
131131
errorMessage.append(e.getKey());
132132
errorMessage.append("] in ");
133-
errorMessage.append(e.getValue());
133+
if (e.getValue().size() <= 3) {
134+
errorMessage.append(e.getValue());
135+
} else {
136+
errorMessage.append(e.getValue().stream().sorted().limit(3).collect(Collectors.toList()));
137+
errorMessage.append(" and [" + (e.getValue().size() - 3) + "] other ");
138+
errorMessage.append(e.getValue().size() == 4 ? "index" : "indices");
139+
}
134140
}
135141
return errorMessage.toString();
136142
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,12 @@ public enum Cap {
229229
/**
230230
* Consider the upper bound when computing the interval in BUCKET auto mode.
231231
*/
232-
BUCKET_INCLUSIVE_UPPER_BOUND;
232+
BUCKET_INCLUSIVE_UPPER_BOUND,
233+
234+
/**
235+
* Changed error messages for fields with conflicting types in different indices.
236+
*/
237+
SHORT_ERROR_MESSAGES_FOR_UNSUPPORTED_FIELDS;
233238

234239
private final boolean snapshotOnly;
235240
private final FeatureFlag featureFlag;

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public void testUnsupportedAndMultiTypedFields() {
6464
LinkedHashSet<String> ipIndices = new LinkedHashSet<>();
6565
ipIndices.add("test1");
6666
ipIndices.add("test2");
67+
ipIndices.add("test3");
68+
ipIndices.add("test4");
69+
ipIndices.add("test5");
6770
LinkedHashMap<String, Set<String>> typesToIndices = new LinkedHashMap<>();
6871
typesToIndices.put("ip", ipIndices);
69-
typesToIndices.put("keyword", Set.of("test3"));
72+
typesToIndices.put("keyword", Set.of("test6"));
7073
EsField multiTypedField = new InvalidMappedField(multiTyped, typesToIndices);
7174

7275
// Also add an unsupported/multityped field under the names `int` and `double` so we can use `LOOKUP int_number_names ...` and
@@ -85,7 +88,7 @@ public void testUnsupportedAndMultiTypedFields() {
8588
);
8689
assertEquals(
8790
"1:22: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
88-
+ " [ip] in [test1, test2], [keyword] in [test3]",
91+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
8992
error("from test* | dissect multi_typed \"%{foo}\"", analyzer)
9093
);
9194

@@ -95,7 +98,7 @@ public void testUnsupportedAndMultiTypedFields() {
9598
);
9699
assertEquals(
97100
"1:19: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
98-
+ " [ip] in [test1, test2], [keyword] in [test3]",
101+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
99102
error("from test* | grok multi_typed \"%{WORD:foo}\"", analyzer)
100103
);
101104

@@ -115,7 +118,7 @@ public void testUnsupportedAndMultiTypedFields() {
115118
);
116119
assertEquals(
117120
"1:23: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
118-
+ " [ip] in [test1, test2], [keyword] in [test3]",
121+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
119122
error("from test* | eval x = multi_typed", analyzer)
120123
);
121124

@@ -125,7 +128,7 @@ public void testUnsupportedAndMultiTypedFields() {
125128
);
126129
assertEquals(
127130
"1:32: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
128-
+ " [ip] in [test1, test2], [keyword] in [test3]",
131+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
129132
error("from test* | eval x = to_lower(multi_typed)", analyzer)
130133
);
131134

@@ -135,7 +138,7 @@ public void testUnsupportedAndMultiTypedFields() {
135138
);
136139
assertEquals(
137140
"1:32: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
138-
+ " [ip] in [test1, test2], [keyword] in [test3]",
141+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
139142
error("from test* | stats count(1) by multi_typed", analyzer)
140143
);
141144
if (EsqlCapabilities.Cap.INLINESTATS.isEnabled()) {
@@ -145,7 +148,7 @@ public void testUnsupportedAndMultiTypedFields() {
145148
);
146149
assertEquals(
147150
"1:38: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
148-
+ " [ip] in [test1, test2], [keyword] in [test3]",
151+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
149152
error("from test* | inlinestats count(1) by multi_typed", analyzer)
150153
);
151154
}
@@ -156,7 +159,7 @@ public void testUnsupportedAndMultiTypedFields() {
156159
);
157160
assertEquals(
158161
"1:27: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
159-
+ " [ip] in [test1, test2], [keyword] in [test3]",
162+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
160163
error("from test* | stats values(multi_typed)", analyzer)
161164
);
162165
if (EsqlCapabilities.Cap.INLINESTATS.isEnabled()) {
@@ -166,7 +169,7 @@ public void testUnsupportedAndMultiTypedFields() {
166169
);
167170
assertEquals(
168171
"1:33: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
169-
+ " [ip] in [test1, test2], [keyword] in [test3]",
172+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
170173
error("from test* | inlinestats values(multi_typed)", analyzer)
171174
);
172175
}
@@ -177,7 +180,7 @@ public void testUnsupportedAndMultiTypedFields() {
177180
);
178181
assertEquals(
179182
"1:27: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
180-
+ " [ip] in [test1, test2], [keyword] in [test3]",
183+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
181184
error("from test* | stats values(multi_typed)", analyzer)
182185
);
183186

@@ -200,7 +203,7 @@ public void testUnsupportedAndMultiTypedFields() {
200203
);
201204
assertEquals(
202205
"1:24: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
203-
+ " [ip] in [test1, test2], [keyword] in [test3]",
206+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
204207
error("from test* | mv_expand multi_typed", analyzer)
205208
);
206209

@@ -210,7 +213,7 @@ public void testUnsupportedAndMultiTypedFields() {
210213
);
211214
assertEquals(
212215
"1:21: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
213-
+ " [ip] in [test1, test2], [keyword] in [test3]",
216+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
214217
error("from test* | rename multi_typed as x", analyzer)
215218
);
216219

@@ -220,7 +223,7 @@ public void testUnsupportedAndMultiTypedFields() {
220223
);
221224
assertEquals(
222225
"1:19: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
223-
+ " [ip] in [test1, test2], [keyword] in [test3]",
226+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
224227
error("from test* | sort multi_typed desc", analyzer)
225228
);
226229

@@ -230,7 +233,7 @@ public void testUnsupportedAndMultiTypedFields() {
230233
);
231234
assertEquals(
232235
"1:20: Cannot use field [multi_typed] due to ambiguities being mapped as [2] incompatible types:"
233-
+ " [ip] in [test1, test2], [keyword] in [test3]",
236+
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
234237
error("from test* | where multi_typed is not null", analyzer)
235238
);
236239
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
setup:
2+
- requires:
3+
capabilities:
4+
- method: POST
5+
path: /_query
6+
parameters: [method, path, parameters, capabilities]
7+
capabilities: [short_error_messages_for_unsupported_fields]
8+
reason: "We changed error messages for unsupported fields in v 8.16"
9+
test_runner_features: [capabilities, allowed_warnings_regex]
10+
11+
- do:
12+
indices.create:
13+
index: ambiguous_1
14+
body:
15+
mappings:
16+
properties:
17+
"name":
18+
type: keyword
19+
20+
- do:
21+
indices.create:
22+
index: ambiguous_2
23+
body:
24+
mappings:
25+
properties:
26+
"name":
27+
type: keyword
28+
29+
- do:
30+
indices.create:
31+
index: ambiguous_3
32+
body:
33+
mappings:
34+
properties:
35+
"name":
36+
type: keyword
37+
38+
- do:
39+
indices.create:
40+
index: ambiguous_4
41+
body:
42+
mappings:
43+
properties:
44+
"name":
45+
type: integer
46+
47+
- do:
48+
indices.create:
49+
index: ambiguous_5
50+
body:
51+
mappings:
52+
properties:
53+
"name":
54+
type: integer
55+
56+
- do:
57+
indices.create:
58+
index: ambiguous_6
59+
body:
60+
mappings:
61+
properties:
62+
"name":
63+
type: integer
64+
65+
- do:
66+
indices.create:
67+
index: ambiguous_7
68+
body:
69+
mappings:
70+
properties:
71+
"name":
72+
type: integer
73+
74+
- do:
75+
indices.create:
76+
index: ambiguous_8
77+
body:
78+
mappings:
79+
properties:
80+
"name":
81+
type: ip
82+
83+
- do:
84+
indices.create:
85+
index: ambiguous_9
86+
body:
87+
mappings:
88+
properties:
89+
"name":
90+
type: ip
91+
92+
- do:
93+
indices.create:
94+
index: ambiguous_10
95+
body:
96+
mappings:
97+
properties:
98+
"name":
99+
type: ip
100+
101+
- do:
102+
indices.create:
103+
index: ambiguous_11
104+
body:
105+
mappings:
106+
properties:
107+
"name":
108+
type: ip
109+
110+
- do:
111+
indices.create:
112+
index: ambiguous_12
113+
body:
114+
mappings:
115+
properties:
116+
"name":
117+
type: ip
118+
119+
---
120+
load many indices with ambiguities:
121+
- do:
122+
catch: '/Cannot use field \[name\] due to ambiguities being mapped as \[3\] incompatible types: \[integer\] in \[ambiguous_4, ambiguous_5, ambiguous_6\] and \[1\] other index, \[ip\] in \[ambiguous_10, ambiguous_11, ambiguous_12\] and \[2\] other indices, \[keyword\] in \[ambiguous_1, ambiguous_2, ambiguous_3\]/'
123+
esql.query:
124+
body:
125+
query: 'FROM ambiguous* | SORT name'
126+

0 commit comments

Comments
 (0)