-
Notifications
You must be signed in to change notification settings - Fork 25.2k
ES|QL: Improve random query generation tests #121750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
luigidellaquila
merged 6 commits into
elastic:main
from
luigidellaquila:esql/update_generative_tests_202502
Feb 7, 2025
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
4dc5ef4
ES|QL: enable random query generation tests
luigidellaquila 4d3bec1
Fix javadoc
luigidellaquila 8dab157
Merge branch 'main' into esql/update_generative_tests_202502
luigidellaquila 61d3e0e
Disable again
luigidellaquila af0d4e8
Merge remote-tracking branch 'luigidellaquila/esql/update_generative_…
luigidellaquila 93e2595
Merge branch 'main' into esql/update_generative_tests_202502
luigidellaquila File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,10 +28,13 @@ public record Column(String name, String type) {} | |
public record QueryExecuted(String query, int depth, List<Column> outputSchema, Exception exception) {} | ||
|
||
public static String sourceCommand(List<String> availabeIndices) { | ||
return switch (randomIntBetween(0, 2)) { | ||
return switch (randomIntBetween(0, 1)) { | ||
case 0 -> from(availabeIndices); | ||
case 1 -> metaFunctions(); | ||
default -> row(); | ||
// case 1 -> metaFunctions(); | ||
default -> from(availabeIndices); | ||
// TODO re-enable ROW. | ||
// now it crashes nodes in some cases: exiting java.lang.AssertionError: estimated row size [0] wasn't set | ||
// default -> row(); | ||
}; | ||
|
||
} | ||
|
@@ -41,8 +44,12 @@ public static String sourceCommand(List<String> availabeIndices) { | |
* @param policies | ||
* @return a new command that can process it as input | ||
*/ | ||
public static String pipeCommand(List<Column> previousOutput, List<CsvTestsDataLoader.EnrichConfig> policies) { | ||
return switch (randomIntBetween(0, 11)) { | ||
public static String pipeCommand( | ||
List<Column> previousOutput, | ||
List<CsvTestsDataLoader.EnrichConfig> policies, | ||
List<GenerativeRestTest.LookupIdx> lookupIndices | ||
) { | ||
return switch (randomIntBetween(0, 12)) { | ||
case 0 -> dissect(previousOutput); | ||
case 1 -> drop(previousOutput); | ||
case 2 -> enrich(previousOutput, policies); | ||
|
@@ -54,10 +61,26 @@ public static String pipeCommand(List<Column> previousOutput, List<CsvTestsDataL | |
case 8 -> rename(previousOutput); | ||
case 9 -> sort(previousOutput); | ||
case 10 -> stats(previousOutput); | ||
case 11 -> join(previousOutput, lookupIndices); | ||
default -> where(previousOutput); | ||
}; | ||
} | ||
|
||
private static String join(List<Column> previousOutput, List<GenerativeRestTest.LookupIdx> lookupIndices) { | ||
|
||
GenerativeRestTest.LookupIdx lookupIdx = randomFrom(lookupIndices); | ||
String lookupIdxName = lookupIdx.idxName(); | ||
String idxKey = lookupIdx.key(); | ||
String keyType = lookupIdx.keyType(); | ||
|
||
var candidateKeys = previousOutput.stream().filter(x -> x.type.equals(keyType)).toList(); | ||
if (candidateKeys.isEmpty()) { | ||
return ""; | ||
} | ||
Column key = randomFrom(candidateKeys); | ||
return "| rename " + key.name + " as " + idxKey + " | lookup join " + lookupIdxName + " on " + idxKey; | ||
} | ||
|
||
private static String where(List<Column> previousOutput) { | ||
// TODO more complex conditions | ||
StringBuilder result = new StringBuilder(" | where "); | ||
|
@@ -191,15 +214,66 @@ private static String keep(List<Column> previousOutput) { | |
} | ||
|
||
private static String randomName(List<Column> previousOutput) { | ||
return previousOutput.get(randomIntBetween(0, previousOutput.size() - 1)).name(); | ||
// we need to exclude <all-fields-projected> | ||
// https://github.com/elastic/elasticsearch/issues/121741 | ||
return randomFrom(previousOutput.stream().filter(x -> x.name().equals("<all-fields-projected>") == false).toList()).name(); | ||
} | ||
|
||
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(); | ||
if (candidates.isEmpty()) { | ||
return null; | ||
} | ||
return randomFrom(candidates).name(); | ||
} | ||
|
||
private static boolean groupable(Column col) { | ||
return col.type.equals("keyword") | ||
|| col.type.equals("text") | ||
|| col.type.equals("long") | ||
|| col.type.equals("integer") | ||
|| col.type.equals("ip") | ||
|| col.type.equals("version"); | ||
Comment on lines
+236
to
+241
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. put those types into a set and simply do a map.contains() |
||
} | ||
|
||
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(); | ||
if (candidates.isEmpty()) { | ||
return null; | ||
} | ||
return randomFrom(candidates).name(); | ||
} | ||
|
||
private static boolean sortable(Column col) { | ||
return col.type.equals("keyword") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same comment as groupable |
||
|| col.type.equals("text") | ||
|| col.type.equals("long") | ||
|| col.type.equals("integer") | ||
|| col.type.equals("ip") | ||
|| col.type.equals("version"); | ||
} | ||
|
||
private static String rename(List<Column> previousOutput) { | ||
int n = randomIntBetween(1, Math.min(3, previousOutput.size())); | ||
List<String> proj = new ArrayList<>(); | ||
List<String> names = new ArrayList<>(previousOutput.stream().map(Column::name).collect(Collectors.toList())); | ||
for (int i = 0; i < n; i++) { | ||
String name = names.remove(randomIntBetween(0, names.size() - 1)); | ||
var colN = randomIntBetween(0, names.size() - 1); | ||
if (previousOutput.get(colN).type().endsWith("_range")) { | ||
// ranges are not fully supported yet | ||
continue; | ||
} | ||
String name = names.remove(colN); | ||
String newName; | ||
if (names.isEmpty() || randomBoolean()) { | ||
newName = randomAlphaOfLength(5); | ||
|
@@ -209,6 +283,9 @@ private static String rename(List<Column> previousOutput) { | |
names.add(newName); | ||
proj.add(name + " AS " + newName); | ||
} | ||
if (proj.isEmpty()) { | ||
return ""; | ||
} | ||
return " | rename " + proj.stream().collect(Collectors.joining(", ")); | ||
} | ||
|
||
|
@@ -227,7 +304,7 @@ private static String drop(List<Column> previousOutput) { | |
name = "*" + name.substring(randomIntBetween(1, name.length() - 1)); | ||
} | ||
} | ||
proj.add(name); | ||
proj.add(name.contains("*") ? name : "`" + name + "`"); | ||
} | ||
return " | drop " + proj.stream().collect(Collectors.joining(", ")); | ||
} | ||
|
@@ -236,7 +313,11 @@ private static String sort(List<Column> previousOutput) { | |
int n = randomIntBetween(1, previousOutput.size()); | ||
Set<String> proj = new HashSet<>(); | ||
for (int i = 0; i < n; i++) { | ||
proj.add(randomName(previousOutput)); | ||
String col = randomSortableName(previousOutput); | ||
if (col == null) { | ||
return "";// no sortable columns | ||
} | ||
proj.add(col); | ||
} | ||
return " | sort " | ||
+ proj.stream() | ||
|
@@ -295,9 +376,10 @@ private static String stats(List<Column> previousOutput) { | |
cmd.append(expression); | ||
} | ||
if (randomBoolean()) { | ||
cmd.append(" by "); | ||
|
||
cmd.append(randomName(nonNull)); | ||
var col = randomGroupableName(nonNull); | ||
if (col != null) { | ||
cmd.append(" by " + col); | ||
} | ||
} | ||
return cmd.toString(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract "" into a constant