@@ -28,10 +28,13 @@ public record Column(String name, String type) {}
28
28
public record QueryExecuted (String query , int depth , List <Column > outputSchema , Exception exception ) {}
29
29
30
30
public static String sourceCommand (List <String > availabeIndices ) {
31
- return switch (randomIntBetween (0 , 2 )) {
31
+ return switch (randomIntBetween (0 , 1 )) {
32
32
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();
35
38
};
36
39
37
40
}
@@ -41,8 +44,12 @@ public static String sourceCommand(List<String> availabeIndices) {
41
44
* @param policies
42
45
* @return a new command that can process it as input
43
46
*/
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 )) {
46
53
case 0 -> dissect (previousOutput );
47
54
case 1 -> drop (previousOutput );
48
55
case 2 -> enrich (previousOutput , policies );
@@ -54,10 +61,26 @@ public static String pipeCommand(List<Column> previousOutput, List<CsvTestsDataL
54
61
case 8 -> rename (previousOutput );
55
62
case 9 -> sort (previousOutput );
56
63
case 10 -> stats (previousOutput );
64
+ case 11 -> join (previousOutput , lookupIndices );
57
65
default -> where (previousOutput );
58
66
};
59
67
}
60
68
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
+
61
84
private static String where (List <Column > previousOutput ) {
62
85
// TODO more complex conditions
63
86
StringBuilder result = new StringBuilder (" | where " );
@@ -191,15 +214,66 @@ private static String keep(List<Column> previousOutput) {
191
214
}
192
215
193
216
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" );
195
264
}
196
265
197
266
private static String rename (List <Column > previousOutput ) {
198
267
int n = randomIntBetween (1 , Math .min (3 , previousOutput .size ()));
199
268
List <String > proj = new ArrayList <>();
200
269
List <String > names = new ArrayList <>(previousOutput .stream ().map (Column ::name ).collect (Collectors .toList ()));
201
270
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 );
203
277
String newName ;
204
278
if (names .isEmpty () || randomBoolean ()) {
205
279
newName = randomAlphaOfLength (5 );
@@ -209,6 +283,9 @@ private static String rename(List<Column> previousOutput) {
209
283
names .add (newName );
210
284
proj .add (name + " AS " + newName );
211
285
}
286
+ if (proj .isEmpty ()) {
287
+ return "" ;
288
+ }
212
289
return " | rename " + proj .stream ().collect (Collectors .joining (", " ));
213
290
}
214
291
@@ -227,7 +304,7 @@ private static String drop(List<Column> previousOutput) {
227
304
name = "*" + name .substring (randomIntBetween (1 , name .length () - 1 ));
228
305
}
229
306
}
230
- proj .add (name );
307
+ proj .add (name . contains ( "*" ) ? name : "`" + name + "`" );
231
308
}
232
309
return " | drop " + proj .stream ().collect (Collectors .joining (", " ));
233
310
}
@@ -236,7 +313,11 @@ private static String sort(List<Column> previousOutput) {
236
313
int n = randomIntBetween (1 , previousOutput .size ());
237
314
Set <String > proj = new HashSet <>();
238
315
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 );
240
321
}
241
322
return " | sort "
242
323
+ proj .stream ()
@@ -295,9 +376,10 @@ private static String stats(List<Column> previousOutput) {
295
376
cmd .append (expression );
296
377
}
297
378
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
+ }
301
383
}
302
384
return cmd .toString ();
303
385
}
0 commit comments