Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions muted-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,6 @@ tests:
- class: org.elasticsearch.xpack.esql.heap_attack.HeapAttackIT
method: testLookupExplosionNoFetch
issue: https://github.com/elastic/elasticsearch/issues/127365
- class: org.elasticsearch.xpack.esql.qa.single_node.GenerativeIT
method: test
issue: https://github.com/elastic/elasticsearch/issues/127536
- class: org.elasticsearch.xpack.test.rest.XPackRestIT
method: test {p0=ml/data_frame_analytics_cat_apis/Test cat data frame analytics all jobs with header}
issue: https://github.com/elastic/elasticsearch/issues/127625
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private static String grok(List<Column> previousOutput) {
result.append(randomIdentifier());
} else {
String fieldName = randomRawName(previousOutput);
if (fieldName.isEmpty()) { // it's a bug, managed later, skipping for now
if (fieldName == null) {
fieldName = randomIdentifier();
}
result.append(fieldName);
Expand Down Expand Up @@ -191,7 +191,7 @@ private static String dissect(List<Column> previousOutput) {
result.append(randomIdentifier());
} else {
String fieldName = randomRawName(previousOutput);
if (fieldName.isEmpty()) { // it's a bug, managed later, skipping for now
if (fieldName == null) {
fieldName = randomIdentifier();
}
result.append(fieldName);
Expand All @@ -210,6 +210,9 @@ private static String keep(List<Column> previousOutput) {
proj.add("*");
} else {
String name = randomName(previousOutput);
if (name == null) {
continue;
}
if (name.length() > 1 && name.startsWith("`") == false && randomIntBetween(0, 100) < 10) {
if (randomBoolean()) {
name = name.substring(0, randomIntBetween(1, name.length() - 1)) + "*";
Expand All @@ -220,31 +223,42 @@ private static String keep(List<Column> previousOutput) {
proj.add(name);
}
}
if (proj.isEmpty()) {
return "";
}
return " | keep " + proj.stream().collect(Collectors.joining(", "));
}

private static String randomName(List<Column> previousOutput) {
String result = randomRawName(previousOutput);
if ((randomBoolean() && result.contains("*") == false)) {
if (result == null) {
return null;
}
if (randomBoolean() && result.contains("*") == false) {
result = "`" + result + "`";
}
return result;
}

/**
* Returns a field name from a list of columns.
* Could be null if none of the fields can be considered
*/
private static String randomRawName(List<Column> previousOutput) {
// we need to exclude <all-fields-projected>
// https://github.com/elastic/elasticsearch/issues/121741
String result = randomFrom(previousOutput.stream().filter(x -> x.name().equals("<all-fields-projected>") == false).toList()).name();
var list = previousOutput.stream().filter(EsqlQueryGenerator::fieldCanBeUsed).toList();
if (list.isEmpty()) {
return null;
}
String result = randomFrom(list).name();
return result;
}

/**
* Returns a field that can be used for grouping.
* Can return null
*/
private static String randomGroupableName(List<Column> previousOutput) {
// we need to exclude <all-fields-projected>
// https://github.com/elastic/elasticsearch/issues/121741
var candidates = previousOutput.stream()
.filter(EsqlQueryGenerator::groupable)
.filter(x -> x.name().equals("<all-fields-projected>") == false)
.toList();
var candidates = previousOutput.stream().filter(EsqlQueryGenerator::groupable).filter(EsqlQueryGenerator::fieldCanBeUsed).toList();
if (candidates.isEmpty()) {
return null;
}
Expand All @@ -260,13 +274,12 @@ private static boolean groupable(Column col) {
|| col.type.equals("version");
}

/**
* returns a field that can be sorted.
* Null if no fields are sortable.
*/
private static String randomSortableName(List<Column> previousOutput) {
// we need to exclude <all-fields-projected>
// https://github.com/elastic/elasticsearch/issues/121741
var candidates = previousOutput.stream()
.filter(EsqlQueryGenerator::sortable)
.filter(x -> x.name().equals("<all-fields-projected>") == false)
.toList();
var candidates = previousOutput.stream().filter(EsqlQueryGenerator::sortable).filter(EsqlQueryGenerator::fieldCanBeUsed).toList();
if (candidates.isEmpty()) {
return null;
}
Expand All @@ -290,10 +303,18 @@ private static String rename(List<Column> previousOutput) {
for (Column column : previousOutput) {
nameToType.put(column.name, column.type);
}
List<String> names = new ArrayList<>(previousOutput.stream().map(Column::name).collect(Collectors.toList()));
List<String> names = new ArrayList<>(
previousOutput.stream().filter(EsqlQueryGenerator::fieldCanBeUsed).map(Column::name).collect(Collectors.toList())
);
if (names.isEmpty()) {
return "";
}
for (int i = 0; i < n; i++) {
if (names.isEmpty()) {
break;
}
var name = randomFrom(names);
if (name.equals("<all-fields-projected>") || nameToType.get(name).endsWith("_range")) {
if (nameToType.get(name).endsWith("_range")) {
// ranges are not fully supported yet
continue;
}
Expand All @@ -306,9 +327,6 @@ private static String rename(List<Column> previousOutput) {
} else {
newName = names.get(randomIntBetween(0, names.size() - 1));
}
if (newName.equals("<all-fields-projected>")) { // it's a bug, managed as an error later
continue;
}
nameToType.put(newName, nameToType.get(name));
if (randomBoolean() && name.startsWith("`") == false) {
name = "`" + name + "`";
Expand All @@ -332,6 +350,9 @@ private static String drop(List<Column> previousOutput) {
Set<String> proj = new HashSet<>();
for (int i = 0; i < n; i++) {
String name = randomRawName(previousOutput);
if (name == null) {
continue;
}
if (name.length() > 1 && name.startsWith("`") == false && randomIntBetween(0, 100) < 10) {
if (randomBoolean()) {
name = name.substring(0, randomIntBetween(1, name.length() - 1)) + "*";
Expand All @@ -343,6 +364,9 @@ private static String drop(List<Column> previousOutput) {
}
proj.add(name);
}
if (proj.isEmpty()) {
return "";
}
return " | drop " + proj.stream().collect(Collectors.joining(", "));
}

Expand All @@ -363,7 +387,11 @@ private static String sort(List<Column> previousOutput) {
}

private static String mvExpand(List<Column> previousOutput) {
return " | mv_expand " + randomName(previousOutput);
String toExpand = randomName(previousOutput);
if (toExpand == null) {
return ""; // no columns to expand
}
return " | mv_expand " + toExpand;
}

private static String eval(List<Column> previousOutput) {
Expand All @@ -376,6 +404,9 @@ private static String eval(List<Column> previousOutput) {
name = randomIdentifier();
} else {
name = randomName(previousOutput);
if (name == null) {
name = randomIdentifier();
}
}
String expression = expression(previousOutput);
if (i > 0) {
Expand All @@ -390,7 +421,10 @@ private static String eval(List<Column> previousOutput) {
}

private static String stats(List<Column> previousOutput) {
List<Column> nonNull = previousOutput.stream().filter(x -> x.type().equals("null") == false).collect(Collectors.toList());
List<Column> nonNull = previousOutput.stream()
.filter(EsqlQueryGenerator::fieldCanBeUsed)
.filter(x -> x.type().equals("null") == false)
.collect(Collectors.toList());
if (nonNull.isEmpty()) {
return ""; // cannot do any stats, just skip
}
Expand All @@ -402,6 +436,9 @@ private static String stats(List<Column> previousOutput) {
name = randomIdentifier();
} else {
name = randomName(previousOutput);
if (name == null) {
name = randomIdentifier();
}
}
String expression = agg(nonNull);
if (i > 0) {
Expand Down Expand Up @@ -433,6 +470,9 @@ private static String agg(List<Column> previousOutput) {
}
// all types
name = randomName(previousOutput);
if (name == null) {
return "count(*)";
}
return switch (randomIntBetween(0, 2)) {
case 0 -> "count(*)";
case 1 -> "count(" + name + ")";
Expand Down Expand Up @@ -529,4 +569,12 @@ private static String randomIdentifier() {
return randomAlphaOfLength(randomIntBetween(8, 12));
}

private static boolean fieldCanBeUsed(Column field) {
return (
// https://github.com/elastic/elasticsearch/issues/121741
field.name().equals("<all-fields-projected>")
// this is a known pathological case, no need to test it for now
|| field.name().equals("<no-fields>")) == false;
}

}