1111import org .elasticsearch .xpack .esql .qa .rest .generative .GenerativeRestTest ;
1212import org .elasticsearch .xpack .esql .qa .rest .generative .command .CommandGenerator ;
1313
14+ import java .util .ArrayList ;
15+ import java .util .HashSet ;
1416import java .util .List ;
1517import java .util .Map ;
18+ import java .util .Set ;
1619
1720import static org .elasticsearch .test .ESTestCase .randomFrom ;
21+ import static org .elasticsearch .test .ESTestCase .randomInt ;
22+ import static org .elasticsearch .test .ESTestCase .randomSubsetOf ;
1823
1924public class LookupJoinGenerator implements CommandGenerator {
2025
@@ -29,15 +34,50 @@ public CommandDescription generate(
2934 ) {
3035 GenerativeRestTest .LookupIdx lookupIdx = randomFrom (schema .lookupIndices ());
3136 String lookupIdxName = lookupIdx .idxName ();
32- String idxKey = lookupIdx .key ();
33- String keyType = lookupIdx .keyType ();
37+ int joinColumnsCount = randomInt (lookupIdx .keys ().size () - 1 ) + 1 ; // at least one column must be used for the join
38+ List <GenerativeRestTest .LookupIdxColumn > joinColumns = randomSubsetOf (joinColumnsCount , lookupIdx .keys ());
39+ List <String > keyNames = new ArrayList <>();
40+ List <String > joinOn = new ArrayList <>();
41+ Set <String > usedColumns = new HashSet <>();
42+ for (GenerativeRestTest .LookupIdxColumn joinColumn : joinColumns ) {
43+ String idxKey = joinColumn .name ();
44+ String keyType = joinColumn .type ();
3445
35- var candidateKeys = previousOutput .stream ().filter (x -> x .type ().equals (keyType )).toList ();
36- if (candidateKeys .isEmpty ()) {
46+ var candidateKeys = previousOutput .stream ().filter (x -> x .type ().equals (keyType )).toList ();
47+ if (candidateKeys .isEmpty ()) {
48+ continue ; // no candidate keys of the right type, skip this column
49+ }
50+ EsqlQueryGenerator .Column key = randomFrom (candidateKeys );
51+ if (usedColumns .contains (key .name ())) {
52+ continue ; // already used this column, skip
53+ } else {
54+ usedColumns .add (key .name ());
55+ }
56+ keyNames .add (key .name ());
57+ joinOn .add (idxKey );
58+ }
59+ if (keyNames .isEmpty ()) {
3760 return EMPTY_DESCRIPTION ;
3861 }
39- EsqlQueryGenerator .Column key = randomFrom (candidateKeys );
40- String cmdString = "| rename " + key .name () + " as " + idxKey + " | lookup join " + lookupIdxName + " on " + idxKey ;
62+ StringBuilder stringBuilder = new StringBuilder ();
63+ for (int i = 0 ; i < keyNames .size (); i ++) {
64+ stringBuilder .append ("| rename " );
65+ stringBuilder .append (keyNames .get (i ));
66+ stringBuilder .append (" as " );
67+ stringBuilder .append (joinOn .get (i ));
68+ }
69+ stringBuilder .append (" | lookup join " ).append (lookupIdxName ).append (" on " );
70+ for (int i = 0 ; i < keyNames .size (); i ++) {
71+ stringBuilder .append (joinOn .get (i ));
72+ if (i < keyNames .size () - 1 ) {
73+ stringBuilder .append (", " );
74+ }
75+ }
76+ stringBuilder .append ("| LIMIT 10" );
77+ if (keyNames .size () > 1 ) {
78+ System .out .println ("GENERATED JOIN ON MORE THAN ONE COLUMN: " + stringBuilder );
79+ }
80+ String cmdString = stringBuilder .toString ();
4181 return new CommandDescription (LOOKUP_JOIN , this , cmdString , Map .of ());
4282 }
4383
0 commit comments