8989 */
9090@ ClusterScope (scope = SUITE , numClientNodes = 1 , numDataNodes = 1 )
9191public class LookupJoinTypesIT extends ESIntegTestCase {
92+ protected Collection <Class <? extends Plugin >> nodePlugins () {
93+ return List .of (EsqlPlugin .class );
94+ }
9295
9396 private static final Map <String , TestConfigs > testConfigurations = new HashMap <>();
9497 static {
@@ -140,6 +143,102 @@ public class LookupJoinTypesIT extends ESIntegTestCase {
140143 }
141144 }
142145
146+ public void testLookupJoinStrings () {
147+ testLookupJoinTypes ("strings" );
148+ }
149+
150+ public void testLookupJoinIntegers () {
151+ testLookupJoinTypes ("integers" );
152+ }
153+
154+ public void testLookupJoinFloats () {
155+ testLookupJoinTypes ("floats" );
156+ }
157+
158+ private void testLookupJoinTypes (String group ) {
159+ initIndexes (group );
160+ initData (group );
161+ for (TestConfig config : testConfigurations .get (group ).configs ()) {
162+ String query = String .format (
163+ Locale .ROOT ,
164+ "FROM index | LOOKUP JOIN %s ON %s | KEEP other" ,
165+ config .indexName (),
166+ config .fieldName ()
167+ );
168+ config .validateMainIndex ();
169+ config .validateLookupIndex ();
170+ config .testQuery (query );
171+ }
172+ }
173+
174+ private void initIndexes (String group ) {
175+ Set <TestConfig > configs = testConfigurations .get (group ).configs ;
176+ // The main index will have many fields, one of each type to use in later type specific joins
177+ String mainFields = "{\n \" properties\" : {\n "
178+ + configs .stream ().map (TestConfig ::mainPropertySpec ).distinct ().collect (Collectors .joining (",\n " ))
179+ + " }\n }\n " ;
180+ assertAcked (prepareCreate ("index" ).setMapping (mainFields ));
181+
182+ Settings .Builder settings = Settings .builder ()
183+ .put ("index.number_of_shards" , 1 )
184+ .put ("index.number_of_replicas" , 0 )
185+ .put ("index.mode" , "lookup" );
186+ configs .forEach (
187+ // Each lookup index will get a document with a field to join on, and a results field to get back
188+ (c ) -> assertAcked (
189+ prepareCreate (c .indexName ()).setSettings (settings .build ())
190+ .setMapping (c .fieldName (), "type=" + c .lookupType ().esType (), "other" , "type=keyword" )
191+ )
192+ );
193+ }
194+
195+ private void initData (String group ) {
196+ Set <TestConfig > configs = testConfigurations .get (group ).configs ;
197+ int docId = 0 ;
198+ for (TestConfig config : configs ) {
199+ String doc = String .format (Locale .ROOT , """
200+ {
201+ %s,
202+ "other": "value"
203+ }
204+ """ , lookupPropertyFor (config ));
205+ index (config .indexName (), "" + (++docId ), doc );
206+ refresh (config .indexName ());
207+ }
208+ List <String > mainProperties = configs .stream ().map (this ::mainPropertyFor ).distinct ().collect (Collectors .toList ());
209+ index ("index" , "1" , String .format (Locale .ROOT , """
210+ {
211+ %s
212+ }
213+ """ , String .join (",\n " , mainProperties )));
214+ refresh ("index" );
215+ }
216+
217+ private String lookupPropertyFor (TestConfig config ) {
218+ return String .format (Locale .ROOT , "\" %s\" : %s" , config .fieldName (), sampleDataTextFor (config .lookupType ()));
219+ }
220+
221+ private String mainPropertyFor (TestConfig config ) {
222+ return String .format (Locale .ROOT , "\" %s\" : %s" , config .fieldName (), sampleDataTextFor (config .mainType ()));
223+ }
224+
225+ private static String sampleDataTextFor (DataType type ) {
226+ return switch (type ) {
227+ case KEYWORD , TEXT -> "\" " + sampleDataFor (type ) + "\" " ;
228+ default -> String .valueOf (sampleDataFor (type ));
229+ };
230+ }
231+
232+ private static Object sampleDataFor (DataType type ) {
233+ return switch (type ) {
234+ case KEYWORD , TEXT -> "key" ;
235+ case BYTE , SHORT , INTEGER -> 1 ;
236+ case LONG -> 1L ;
237+ case FLOAT , DOUBLE -> 1.0 ;
238+ default -> throw new IllegalArgumentException ("Unsupported type: " + type );
239+ };
240+ }
241+
143242 private record TestConfigs (String group , Set <TestConfig > configs ) {
144243
145244 private void addPasses (DataType mainType , DataType lookupType ) {
@@ -230,7 +329,7 @@ private static void validateIndex(String indexName, String fieldName, Object exp
230329 }
231330 }
232331
233- record TestConfigPasses (DataType mainType , DataType lookupType , boolean hasResults ) implements TestConfig {
332+ private record TestConfigPasses (DataType mainType , DataType lookupType , boolean hasResults ) implements TestConfig {
234333 @ Override
235334 public void testQuery (String query ) {
236335 try (var response = EsqlQueryRequestBuilder .newRequestBuilder (client ()).query (query ).get ()) {
@@ -246,7 +345,7 @@ public void testQuery(String query) {
246345 }
247346 }
248347
249- record TestConfigFails <E extends Exception >(DataType mainType , DataType lookupType , Class <E > exception , Consumer <E > assertion )
348+ private record TestConfigFails <E extends Exception >(DataType mainType , DataType lookupType , Class <E > exception , Consumer <E > assertion )
250349 implements
251350 TestConfig {
252351 @ Override
@@ -263,104 +362,4 @@ public void testQuery(String query) {
263362 assertion ().accept (e );
264363 }
265364 }
266-
267- protected Collection <Class <? extends Plugin >> nodePlugins () {
268- return List .of (EsqlPlugin .class );
269- }
270-
271- public void testLookupJoinStrings () {
272- testLookupJoinTypes ("strings" );
273- }
274-
275- public void testLookupJoinIntegers () {
276- testLookupJoinTypes ("integers" );
277- }
278-
279- public void testLookupJoinFloats () {
280- testLookupJoinTypes ("floats" );
281- }
282-
283- private void testLookupJoinTypes (String group ) {
284- initIndexes (group );
285- initData (group );
286- for (TestConfig config : testConfigurations .get (group ).configs ()) {
287- String query = String .format (
288- Locale .ROOT ,
289- "FROM index | LOOKUP JOIN %s ON %s | KEEP other" ,
290- config .indexName (),
291- config .fieldName ()
292- );
293- config .validateMainIndex ();
294- config .validateLookupIndex ();
295- config .testQuery (query );
296- }
297- }
298-
299- private void initIndexes (String group ) {
300- Set <TestConfig > configs = testConfigurations .get (group ).configs ;
301- // The main index will have many fields, one of each type to use in later type specific joins
302- String mainFields = "{\n \" properties\" : {\n "
303- + configs .stream ().map (TestConfig ::mainPropertySpec ).distinct ().collect (Collectors .joining (",\n " ))
304- + " }\n }\n " ;
305- assertAcked (prepareCreate ("index" ).setMapping (mainFields ));
306-
307- Settings .Builder settings = Settings .builder ()
308- .put ("index.number_of_shards" , 1 )
309- .put ("index.number_of_replicas" , 0 )
310- .put ("index.mode" , "lookup" );
311- configs .forEach (
312- // Each lookup index will get a document with a field to join on, and a results field to get back
313- (c ) -> assertAcked (
314- prepareCreate (c .indexName ()).setSettings (settings .build ())
315- .setMapping (c .fieldName (), "type=" + c .lookupType ().esType (), "other" , "type=keyword" )
316- )
317- );
318- }
319-
320- private void initData (String group ) {
321- Set <TestConfig > configs = testConfigurations .get (group ).configs ;
322- int docId = 0 ;
323- for (TestConfig config : configs ) {
324- String doc = String .format (Locale .ROOT , """
325- {
326- %s,
327- "other": "value"
328- }
329- """ , lookupPropertyFor (config ));
330- index (config .indexName (), "" + (++docId ), doc );
331- refresh (config .indexName ());
332- }
333- List <String > mainProperties = configs .stream ().map (this ::mainPropertyFor ).distinct ().collect (Collectors .toList ());
334- index ("index" , "1" , String .format (Locale .ROOT , """
335- {
336- %s
337- }
338- """ , String .join (",\n " , mainProperties )));
339- refresh ("index" );
340- }
341-
342- private String lookupPropertyFor (TestConfig config ) {
343- return String .format (Locale .ROOT , "\" %s\" : %s" , config .fieldName (), sampleDataTextFor (config .lookupType ()));
344- }
345-
346- private String mainPropertyFor (TestConfig config ) {
347- return String .format (Locale .ROOT , "\" %s\" : %s" , config .fieldName (), sampleDataTextFor (config .mainType ()));
348- }
349-
350- private static String sampleDataTextFor (DataType type ) {
351- return switch (type ) {
352- case KEYWORD , TEXT -> "\" " + sampleDataFor (type ) + "\" " ;
353- default -> String .valueOf (sampleDataFor (type ));
354- };
355- }
356-
357- private static Object sampleDataFor (DataType type ) {
358- return switch (type ) {
359- case KEYWORD , TEXT -> "key" ;
360- case BYTE , SHORT , INTEGER -> 1 ;
361- case LONG -> 1L ;
362- case FLOAT , DOUBLE -> 1.0 ;
363- default -> throw new IllegalArgumentException ("Unsupported type: " + type );
364- };
365- }
366365}
0 commit comments