@@ -28,10 +28,13 @@ public record Column(String name, String type) {}
2828 public record QueryExecuted (String query , int depth , List <Column > outputSchema , Exception exception ) {}
2929
3030 public static String sourceCommand (List <String > availabeIndices ) {
31- return switch (randomIntBetween (0 , 2 )) {
31+ return switch (randomIntBetween (0 , 1 )) {
3232 case 0 -> from (availabeIndices );
33- case 1 -> metaFunctions ();
34- default -> row ();
33+ // case 1 -> metaFunctions();
34+ default -> from (availabeIndices );
35+ // TODO re-enable ROW.
36+ // now it crashes nodes in some cases: exiting java.lang.AssertionError: estimated row size [0] wasn't set
37+ // default -> row();
3538 };
3639
3740 }
@@ -41,8 +44,12 @@ public static String sourceCommand(List<String> availabeIndices) {
4144 * @param policies
4245 * @return a new command that can process it as input
4346 */
44- public static String pipeCommand (List <Column > previousOutput , List <CsvTestsDataLoader .EnrichConfig > policies ) {
45- return switch (randomIntBetween (0 , 11 )) {
47+ public static String pipeCommand (
48+ List <Column > previousOutput ,
49+ List <CsvTestsDataLoader .EnrichConfig > policies ,
50+ List <GenerativeRestTest .LookupIdx > lookupIndices
51+ ) {
52+ return switch (randomIntBetween (0 , 12 )) {
4653 case 0 -> dissect (previousOutput );
4754 case 1 -> drop (previousOutput );
4855 case 2 -> enrich (previousOutput , policies );
@@ -54,10 +61,26 @@ public static String pipeCommand(List<Column> previousOutput, List<CsvTestsDataL
5461 case 8 -> rename (previousOutput );
5562 case 9 -> sort (previousOutput );
5663 case 10 -> stats (previousOutput );
64+ case 11 -> join (previousOutput , lookupIndices );
5765 default -> where (previousOutput );
5866 };
5967 }
6068
69+ private static String join (List <Column > previousOutput , List <GenerativeRestTest .LookupIdx > lookupIndices ) {
70+
71+ GenerativeRestTest .LookupIdx lookupIdx = randomFrom (lookupIndices );
72+ String lookupIdxName = lookupIdx .idxName ();
73+ String idxKey = lookupIdx .key ();
74+ String keyType = lookupIdx .keyType ();
75+
76+ var candidateKeys = previousOutput .stream ().filter (x -> x .type .equals (keyType )).toList ();
77+ if (candidateKeys .isEmpty ()) {
78+ return "" ;
79+ }
80+ Column key = randomFrom (candidateKeys );
81+ return "| rename " + key .name + " as " + idxKey + " | lookup join " + lookupIdxName + " on " + idxKey ;
82+ }
83+
6184 private static String where (List <Column > previousOutput ) {
6285 // TODO more complex conditions
6386 StringBuilder result = new StringBuilder (" | where " );
@@ -191,15 +214,66 @@ private static String keep(List<Column> previousOutput) {
191214 }
192215
193216 private static String randomName (List <Column > previousOutput ) {
194- return previousOutput .get (randomIntBetween (0 , previousOutput .size () - 1 )).name ();
217+ // we need to exclude <all-fields-projected>
218+ // https://github.com/elastic/elasticsearch/issues/121741
219+ return randomFrom (previousOutput .stream ().filter (x -> x .name ().equals ("<all-fields-projected>" ) == false ).toList ()).name ();
220+ }
221+
222+ private static String randomGroupableName (List <Column > previousOutput ) {
223+ // we need to exclude <all-fields-projected>
224+ // https://github.com/elastic/elasticsearch/issues/121741
225+ var candidates = previousOutput .stream ()
226+ .filter (EsqlQueryGenerator ::groupable )
227+ .filter (x -> x .name ().equals ("<all-fields-projected>" ) == false )
228+ .toList ();
229+ if (candidates .isEmpty ()) {
230+ return null ;
231+ }
232+ return randomFrom (candidates ).name ();
233+ }
234+
235+ private static boolean groupable (Column col ) {
236+ return col .type .equals ("keyword" )
237+ || col .type .equals ("text" )
238+ || col .type .equals ("long" )
239+ || col .type .equals ("integer" )
240+ || col .type .equals ("ip" )
241+ || col .type .equals ("version" );
242+ }
243+
244+ private static String randomSortableName (List <Column > previousOutput ) {
245+ // we need to exclude <all-fields-projected>
246+ // https://github.com/elastic/elasticsearch/issues/121741
247+ var candidates = previousOutput .stream ()
248+ .filter (EsqlQueryGenerator ::sortable )
249+ .filter (x -> x .name ().equals ("<all-fields-projected>" ) == false )
250+ .toList ();
251+ if (candidates .isEmpty ()) {
252+ return null ;
253+ }
254+ return randomFrom (candidates ).name ();
255+ }
256+
257+ private static boolean sortable (Column col ) {
258+ return col .type .equals ("keyword" )
259+ || col .type .equals ("text" )
260+ || col .type .equals ("long" )
261+ || col .type .equals ("integer" )
262+ || col .type .equals ("ip" )
263+ || col .type .equals ("version" );
195264 }
196265
197266 private static String rename (List <Column > previousOutput ) {
198267 int n = randomIntBetween (1 , Math .min (3 , previousOutput .size ()));
199268 List <String > proj = new ArrayList <>();
200269 List <String > names = new ArrayList <>(previousOutput .stream ().map (Column ::name ).collect (Collectors .toList ()));
201270 for (int i = 0 ; i < n ; i ++) {
202- String name = names .remove (randomIntBetween (0 , names .size () - 1 ));
271+ var colN = randomIntBetween (0 , names .size () - 1 );
272+ if (previousOutput .get (colN ).type ().endsWith ("_range" )) {
273+ // ranges are not fully supported yet
274+ continue ;
275+ }
276+ String name = names .remove (colN );
203277 String newName ;
204278 if (names .isEmpty () || randomBoolean ()) {
205279 newName = randomAlphaOfLength (5 );
@@ -209,6 +283,9 @@ private static String rename(List<Column> previousOutput) {
209283 names .add (newName );
210284 proj .add (name + " AS " + newName );
211285 }
286+ if (proj .isEmpty ()) {
287+ return "" ;
288+ }
212289 return " | rename " + proj .stream ().collect (Collectors .joining (", " ));
213290 }
214291
@@ -227,7 +304,7 @@ private static String drop(List<Column> previousOutput) {
227304 name = "*" + name .substring (randomIntBetween (1 , name .length () - 1 ));
228305 }
229306 }
230- proj .add (name );
307+ proj .add (name . contains ( "*" ) ? name : "`" + name + "`" );
231308 }
232309 return " | drop " + proj .stream ().collect (Collectors .joining (", " ));
233310 }
@@ -236,7 +313,11 @@ private static String sort(List<Column> previousOutput) {
236313 int n = randomIntBetween (1 , previousOutput .size ());
237314 Set <String > proj = new HashSet <>();
238315 for (int i = 0 ; i < n ; i ++) {
239- proj .add (randomName (previousOutput ));
316+ String col = randomSortableName (previousOutput );
317+ if (col == null ) {
318+ return "" ;// no sortable columns
319+ }
320+ proj .add (col );
240321 }
241322 return " | sort "
242323 + proj .stream ()
@@ -295,9 +376,10 @@ private static String stats(List<Column> previousOutput) {
295376 cmd .append (expression );
296377 }
297378 if (randomBoolean ()) {
298- cmd .append (" by " );
299-
300- cmd .append (randomName (nonNull ));
379+ var col = randomGroupableName (nonNull );
380+ if (col != null ) {
381+ cmd .append (" by " + col );
382+ }
301383 }
302384 return cmd .toString ();
303385 }
0 commit comments