Skip to content

Commit ced420e

Browse files
committed
Improve lookup join error messages in ES|QL
1 parent 3a1aa8b commit ced420e

File tree

2 files changed

+62
-3
lines changed
  • x-pack/plugin/esql/src

2 files changed

+62
-3
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/join/LookupJoin.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ public void postAnalysisVerification(Failures failures) {
8989
right().forEachDown(EsRelation.class, esr -> {
9090
var indexNameWithModes = esr.indexNameWithModes();
9191
if (indexNameWithModes.size() != 1) {
92-
failures.add(
93-
fail(esr, "invalid [{}] resolution in lookup mode to [{}] indices", esr.indexPattern(), indexNameWithModes.size())
94-
);
92+
String errorMessage = indexNameWithModes.isEmpty()
93+
? "Index [" + esr.indexPattern() + "] exists, but no valid fields for LOOKUP JOIN were found"
94+
: "Invalid [" + esr.indexPattern() + "] resolution in lookup mode to [" + indexNameWithModes.size() + "] indices";
95+
failures.add(fail(esr, errorMessage));
9596
} else if (indexNameWithModes.values().iterator().next() != IndexMode.LOOKUP) {
9697
failures.add(
9798
fail(

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plan/logical/JoinTests.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@
77

88
package org.elasticsearch.xpack.esql.plan.logical;
99

10+
import java.util.Collections;
11+
import java.util.Map;
12+
13+
import org.elasticsearch.index.IndexMode;
1014
import org.elasticsearch.test.ESTestCase;
15+
import org.elasticsearch.xpack.esql.common.Failures;
1116
import org.elasticsearch.xpack.esql.core.expression.Alias;
1217
import org.elasticsearch.xpack.esql.core.expression.Attribute;
1318
import org.elasticsearch.xpack.esql.core.expression.AttributeSet;
1419
import org.elasticsearch.xpack.esql.core.expression.Expression;
20+
import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
1521
import org.elasticsearch.xpack.esql.core.expression.Literal;
1622
import org.elasticsearch.xpack.esql.core.tree.Source;
1723
import org.elasticsearch.xpack.esql.core.type.DataType;
24+
import org.elasticsearch.xpack.esql.core.type.EsField;
1825
import org.elasticsearch.xpack.esql.plan.logical.join.Join;
1926
import org.elasticsearch.xpack.esql.plan.logical.join.JoinConfig;
2027
import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes;
@@ -23,6 +30,8 @@
2330
import java.util.List;
2431
import java.util.Set;
2532

33+
import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin;
34+
2635
public class JoinTests extends ESTestCase {
2736
@AwaitsFix(bugUrl = "Test needs updating to the new JOIN planning")
2837
public void testExpressionsAndReferences() {
@@ -99,4 +108,53 @@ public void testTransformExprs() {
99108
private static Alias aliasForLiteral(String name) {
100109
return new Alias(Source.EMPTY, name, new Literal(Source.EMPTY, 1, DataType.INTEGER));
101110
}
111+
112+
public void testLookupJoinErrorMessage() {
113+
Failures failures = new Failures();
114+
115+
String indexPattern = "test1";
116+
Map<String, IndexMode> indexNameWithModes = Collections.emptyMap();
117+
118+
EsRelation fakeRelation = new EsRelation(Source.EMPTY, indexPattern, IndexMode.LOOKUP, indexNameWithModes, List.of());
119+
120+
EsField empNoEsField = new EsField("emp_no", DataType.INTEGER, Collections.emptyMap(), false);
121+
FieldAttribute empNoField = new FieldAttribute(Source.EMPTY, "emp_no", empNoEsField);
122+
Alias empNoAlias = new Alias(Source.EMPTY, "emp_no", empNoField);
123+
LogicalPlan left = new Row(Source.EMPTY, List.of(empNoAlias));
124+
125+
LookupJoin lookupJoin = new LookupJoin(Source.EMPTY, left, fakeRelation,
126+
new JoinConfig(JoinTypes.LEFT, List.of(), List.of(), List.of()));
127+
128+
lookupJoin.postAnalysisVerification(failures);
129+
130+
String expectedMessage = "Index [test1] exists, but no valid fields for LOOKUP JOIN were found";
131+
assertTrue(failures.toString().contains(expectedMessage));
132+
}
133+
134+
public void testLookupJoinErrorMessage_MultipleIndices() {
135+
Failures failures = new Failures();
136+
137+
String indexPattern = "test1";
138+
Map<String, IndexMode> indexNameWithModes = Map.of(
139+
"test1", IndexMode.LOOKUP,
140+
"test2", IndexMode.LOOKUP
141+
);
142+
143+
EsField languagesEsField = new EsField("languages", DataType.KEYWORD, Collections.emptyMap(), true);
144+
FieldAttribute languagesField = new FieldAttribute(Source.EMPTY, "languages", languagesEsField);
145+
EsRelation fakeRelation = new EsRelation(Source.EMPTY, indexPattern, IndexMode.LOOKUP, indexNameWithModes, List.of(languagesField));
146+
147+
EsField empNoEsField = new EsField("emp_no", DataType.INTEGER, Collections.emptyMap(), false);
148+
FieldAttribute empNoField = new FieldAttribute(Source.EMPTY, "emp_no", empNoEsField);
149+
Alias empNoAlias = new Alias(Source.EMPTY, "emp_no", empNoField);
150+
LogicalPlan left = new Row(Source.EMPTY, List.of(empNoAlias));
151+
152+
LookupJoin lookupJoin = new LookupJoin(Source.EMPTY, left, fakeRelation,
153+
new JoinConfig(JoinTypes.LEFT, List.of(), List.of(), List.of()));
154+
155+
lookupJoin.postAnalysisVerification(failures);
156+
157+
String expectedMessage = "Invalid [test1] resolution in lookup mode to [2] indices";
158+
assertTrue(failures.toString().contains(expectedMessage));
159+
}
102160
}

0 commit comments

Comments
 (0)