@@ -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