1010import org .elasticsearch .action .admin .indices .alias .IndicesAliasesRequest ;
1111import org .elasticsearch .action .admin .indices .alias .IndicesAliasesRequestBuilder ;
1212import org .elasticsearch .client .internal .Client ;
13+ import org .elasticsearch .common .settings .Settings ;
1314import org .elasticsearch .xpack .core .enrich .EnrichPolicy ;
1415import org .elasticsearch .xpack .core .enrich .action .ExecuteEnrichPolicyAction ;
1516import org .elasticsearch .xpack .core .enrich .action .PutEnrichPolicyAction ;
@@ -289,6 +290,9 @@ public void testLookupJoinMissingKey() throws IOException {
289290 populateLookupIndex (REMOTE_CLUSTER_1 , "values_lookup" , 10 );
290291
291292 setSkipUnavailable (REMOTE_CLUSTER_1 , true );
293+
294+ Exception ex ;
295+
292296 try (
293297 // Using local_tag as key which is not present in remote index
294298 EsqlQueryResponse resp = runQuery (
@@ -362,10 +366,7 @@ public void testLookupJoinMissingKey() throws IOException {
362366 }
363367
364368 // TODO: verify whether this should be an error or not when the key field is missing
365- Exception ex = expectThrows (
366- VerificationException .class ,
367- () -> runQuery ("FROM c*:logs-* | LOOKUP JOIN values_lookup ON v" , randomBoolean ())
368- );
369+ ex = expectThrows (VerificationException .class , () -> runQuery ("FROM c*:logs-* | LOOKUP JOIN values_lookup ON v" , randomBoolean ()));
369370 assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
370371
371372 ex = expectThrows (
@@ -374,6 +375,25 @@ public void testLookupJoinMissingKey() throws IOException {
374375 );
375376 assertThat (ex .getMessage (), containsString ("Unknown column [local_tag] in right side of join" ));
376377
378+ // Add KEEP clause to try and trick the field-caps result parser into returning empty mapping
379+ ex = expectThrows (
380+ VerificationException .class ,
381+ () -> runQuery ("FROM logs-* | LOOKUP JOIN values_lookup ON v | KEEP v" , randomBoolean ())
382+ );
383+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
384+
385+ ex = expectThrows (
386+ VerificationException .class ,
387+ () -> runQuery ("FROM logs-*,c*:logs-* | LOOKUP JOIN values_lookup ON v | KEEP v" , randomBoolean ())
388+ );
389+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
390+
391+ ex = expectThrows (
392+ VerificationException .class ,
393+ () -> runQuery ("FROM c*:logs-* | LOOKUP JOIN values_lookup ON v | KEEP v" , randomBoolean ())
394+ );
395+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
396+
377397 setSkipUnavailable (REMOTE_CLUSTER_1 , false );
378398 try (
379399 // Using local_tag as key which is not present in remote index
@@ -393,6 +413,42 @@ public void testLookupJoinMissingKey() throws IOException {
393413 // FIXME: verify whether we need to succeed or fail here
394414 assertThat (remoteCluster .getStatus (), equalTo (EsqlExecutionInfo .Cluster .Status .SUCCESSFUL ));
395415 }
416+
417+ // Add KEEP clause to try and trick the field-caps result parser into returning empty mapping
418+ ex = expectThrows (
419+ VerificationException .class ,
420+ () -> runQuery ("FROM c*:logs-* | LOOKUP JOIN values_lookup ON v | KEEP v" , randomBoolean ())
421+ );
422+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
423+
424+ ex = expectThrows (
425+ VerificationException .class ,
426+ () -> runQuery ("FROM logs-*,c*:logs-* | LOOKUP JOIN values_lookup ON v | KEEP v" , randomBoolean ())
427+ );
428+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
429+ }
430+
431+ public void testLookupJoinEmptyIndex () throws IOException {
432+ setupClusters (2 );
433+ populateEmptyIndices (LOCAL_CLUSTER , "values_lookup" );
434+ populateEmptyIndices (REMOTE_CLUSTER_1 , "values_lookup" );
435+
436+ // Should work the same with both settings
437+ setSkipUnavailable (REMOTE_CLUSTER_1 , randomBoolean ());
438+
439+ Exception ex ;
440+ for (String index : List .of ("values_lookup" , "values_lookup_map" , "values_lookup_map_lookup" )) {
441+ ex = expectThrows (
442+ VerificationException .class ,
443+ () -> runQuery ("FROM logs-* | LOOKUP JOIN " + index + " ON v | KEEP v" , randomBoolean ())
444+ );
445+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
446+ ex = expectThrows (
447+ VerificationException .class ,
448+ () -> runQuery ("FROM c*:logs-* | LOOKUP JOIN " + index + " ON v | KEEP v" , randomBoolean ())
449+ );
450+ assertThat (ex .getMessage (), containsString ("Unknown column [v] in right side of join" ));
451+ }
396452 }
397453
398454 public void testLookupJoinIndexMode () throws IOException {
@@ -528,4 +584,23 @@ protected void setupAlias(String clusterAlias, String indexName, String aliasNam
528584 assertAcked (client .admin ().indices ().aliases (indicesAliasesRequestBuilder .request ()));
529585 }
530586
587+ protected void populateEmptyIndices (String clusterAlias , String indexName ) {
588+ Client client = client (clusterAlias );
589+ // Empty body
590+ assertAcked (client .admin ().indices ().prepareCreate (indexName ));
591+ client .admin ().indices ().prepareRefresh (indexName ).get ();
592+ // mappings + settings
593+ assertAcked (
594+ client .admin ()
595+ .indices ()
596+ .prepareCreate (indexName + "_map_lookup" )
597+ .setMapping ()
598+ .setSettings (Settings .builder ().put ("index.mode" , "lookup" ))
599+ );
600+ client .admin ().indices ().prepareRefresh (indexName + "_map_lookup" ).get ();
601+ // mappings only
602+ assertAcked (client .admin ().indices ().prepareCreate (indexName + "_map" ).setMapping ());
603+ client .admin ().indices ().prepareRefresh (indexName + "_map" ).get ();
604+ }
605+
531606}
0 commit comments