Skip to content

Commit c179cea

Browse files
Add Generative tests for Lookup Join On Multiple Columns
1 parent fc1c63b commit c179cea

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/GenerativeRestTest.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,24 @@ private List<String> availableIndices() throws IOException {
215215
.toList();
216216
}
217217

218-
public record LookupIdx(String idxName, String key, String keyType) {}
218+
public record LookupIdxColumn(String name, String type) {}
219+
220+
public record LookupIdx(String idxName, List<LookupIdxColumn> keys) {}
219221

220222
private List<LookupIdx> lookupIndices() {
221223
List<LookupIdx> result = new ArrayList<>();
222224
// we don't have key info from the dataset loader, let's hardcode it for now
223-
result.add(new LookupIdx("languages_lookup", "language_code", "integer"));
224-
result.add(new LookupIdx("message_types_lookup", "message", "keyword"));
225+
result.add(new LookupIdx("languages_lookup", List.of(new LookupIdxColumn("language_code", "integer"))));
226+
result.add(new LookupIdx("message_types_lookup", List.of(new LookupIdxColumn("message", "keyword"))));
227+
List<LookupIdxColumn> multiColumnJoinableLookupKeys = List.of(
228+
new LookupIdxColumn("id_int", "integer"),
229+
new LookupIdxColumn("name_str", "keyword"),
230+
new LookupIdxColumn("is_active_bool", "boolean"),
231+
new LookupIdxColumn("ip_addr", "ip"),
232+
new LookupIdxColumn("other1", "keyword"),
233+
new LookupIdxColumn("other2", "integer")
234+
);
235+
result.add(new LookupIdx("multi_column_joinable_lookup", multiColumnJoinableLookupKeys));
225236
return result;
226237
}
227238

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/generative/command/pipe/LookupJoinGenerator.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
import org.elasticsearch.xpack.esql.qa.rest.generative.GenerativeRestTest;
1212
import org.elasticsearch.xpack.esql.qa.rest.generative.command.CommandGenerator;
1313

14+
import java.util.ArrayList;
15+
import java.util.HashSet;
1416
import java.util.List;
1517
import java.util.Map;
18+
import java.util.Set;
1619

1720
import static org.elasticsearch.test.ESTestCase.randomFrom;
21+
import static org.elasticsearch.test.ESTestCase.randomInt;
22+
import static org.elasticsearch.test.ESTestCase.randomSubsetOf;
1823

1924
public class LookupJoinGenerator implements CommandGenerator {
2025

@@ -29,15 +34,50 @@ public CommandDescription generate(
2934
) {
3035
GenerativeRestTest.LookupIdx lookupIdx = randomFrom(schema.lookupIndices());
3136
String lookupIdxName = lookupIdx.idxName();
32-
String idxKey = lookupIdx.key();
33-
String keyType = lookupIdx.keyType();
37+
int joinColumnsCount = randomInt(lookupIdx.keys().size() - 1) + 1; // at least one column must be used for the join
38+
List<GenerativeRestTest.LookupIdxColumn> joinColumns = randomSubsetOf(joinColumnsCount, lookupIdx.keys());
39+
List<String> keyNames = new ArrayList<>();
40+
List<String> joinOn = new ArrayList<>();
41+
Set<String> usedColumns = new HashSet<>();
42+
for (GenerativeRestTest.LookupIdxColumn joinColumn : joinColumns) {
43+
String idxKey = joinColumn.name();
44+
String keyType = joinColumn.type();
3445

35-
var candidateKeys = previousOutput.stream().filter(x -> x.type().equals(keyType)).toList();
36-
if (candidateKeys.isEmpty()) {
46+
var candidateKeys = previousOutput.stream().filter(x -> x.type().equals(keyType)).toList();
47+
if (candidateKeys.isEmpty()) {
48+
continue; // no candidate keys of the right type, skip this column
49+
}
50+
EsqlQueryGenerator.Column key = randomFrom(candidateKeys);
51+
if (usedColumns.contains(key.name())) {
52+
continue; // already used this column, skip
53+
} else {
54+
usedColumns.add(key.name());
55+
}
56+
keyNames.add(key.name());
57+
joinOn.add(idxKey);
58+
}
59+
if (keyNames.isEmpty()) {
3760
return EMPTY_DESCRIPTION;
3861
}
39-
EsqlQueryGenerator.Column key = randomFrom(candidateKeys);
40-
String cmdString = "| rename " + key.name() + " as " + idxKey + " | lookup join " + lookupIdxName + " on " + idxKey;
62+
StringBuilder stringBuilder = new StringBuilder();
63+
for (int i = 0; i < keyNames.size(); i++) {
64+
stringBuilder.append("| rename ");
65+
stringBuilder.append(keyNames.get(i));
66+
stringBuilder.append(" as ");
67+
stringBuilder.append(joinOn.get(i));
68+
}
69+
stringBuilder.append(" | lookup join ").append(lookupIdxName).append(" on ");
70+
for (int i = 0; i < keyNames.size(); i++) {
71+
stringBuilder.append(joinOn.get(i));
72+
if (i < keyNames.size() - 1) {
73+
stringBuilder.append(", ");
74+
}
75+
}
76+
stringBuilder.append("| LIMIT 10");
77+
if (keyNames.size() > 1) {
78+
System.out.println("GENERATED JOIN ON MORE THAN ONE COLUMN: " + stringBuilder);
79+
}
80+
String cmdString = stringBuilder.toString();
4181
return new CommandDescription(LOOKUP_JOIN, this, cmdString, Map.of());
4282
}
4383

0 commit comments

Comments
 (0)