Skip to content

Commit 3b13977

Browse files
authored
Fix queries with missing index, skip_unavailable and filters (#130344)
* Fix queries with missing index, skip_unavailable and filters
1 parent 8bd4645 commit 3b13977

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

docs/changelog/130344.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 130344
2+
summary: "Fix queries with missing index, `skip_unavailable` and filters"
3+
area: ES|QL
4+
type: bug
5+
issues: []

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/CrossClusterQueryWithFiltersIT.java

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,13 @@ public void testFilterWithMissingRemoteIndex() {
313313
new RangeQueryBuilder("@timestamp").from("2025-01-01").to("now")
314314
)) {
315315
count++;
316-
// Local index missing
316+
// Remote index missing
317317
VerificationException e = expectThrows(
318318
VerificationException.class,
319319
() -> runQuery("from cluster-a:missing", randomBoolean(), filter).close()
320320
);
321321
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
322-
// Local index missing + wildcards
322+
// Remote index missing + wildcards
323323
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime RemoteException
324324
var ie = expectThrows(
325325
RemoteException.class,
@@ -352,6 +352,66 @@ public void testFilterWithMissingRemoteIndex() {
352352
}
353353
}
354354

355+
public void testFilterWithMissingRemoteIndexSkipUnavailable() {
356+
int docsTest1 = 50;
357+
int docsTest2 = 30;
358+
int localShards = randomIntBetween(1, 5);
359+
int remoteShards = randomIntBetween(1, 5);
360+
populateDateIndex(LOCAL_CLUSTER, LOCAL_INDEX, localShards, docsTest1, "2024-11-26");
361+
populateDateIndex(REMOTE_CLUSTER_1, REMOTE_INDEX, remoteShards, docsTest2, "2023-11-26");
362+
setSkipUnavailable(REMOTE_CLUSTER_1, true);
363+
364+
int count = 0;
365+
for (var filter : List.of(
366+
new RangeQueryBuilder("@timestamp").from("2023-01-01").to("now"),
367+
new RangeQueryBuilder("@timestamp").from("2024-01-01").to("now"),
368+
new RangeQueryBuilder("@timestamp").from("2025-01-01").to("now")
369+
)) {
370+
count++;
371+
try (EsqlQueryResponse resp = runQuery("from cluster-a:missing,logs-1", randomBoolean(), filter)) {
372+
List<List<Object>> values = getValuesList(resp);
373+
assertThat(values, hasSize(count > 2 ? 0 : docsTest1));
374+
EsqlExecutionInfo executionInfo = resp.getExecutionInfo();
375+
assertNotNull(executionInfo);
376+
assertThat(executionInfo.isCrossClusterSearch(), is(true));
377+
long overallTookMillis = executionInfo.overallTook().millis();
378+
assertThat(overallTookMillis, greaterThanOrEqualTo(0L));
379+
380+
EsqlExecutionInfo.Cluster remoteCluster = executionInfo.getCluster(REMOTE_CLUSTER_1);
381+
assertClusterMetadataSkipped(remoteCluster, overallTookMillis, "missing");
382+
assertThat(remoteCluster.getFailures(), hasSize(1));
383+
var fail = remoteCluster.getFailures().get(0);
384+
assertThat(fail.getCause().getMessage(), containsString("Unknown index [cluster-a:missing]"));
385+
}
386+
387+
try (EsqlQueryResponse resp = runQuery("from cluster-a:missing,cluster-a:logs-*", randomBoolean(), filter)) {
388+
List<List<Object>> values = getValuesList(resp);
389+
assertThat(values, hasSize(0));
390+
EsqlExecutionInfo executionInfo = resp.getExecutionInfo();
391+
assertNotNull(executionInfo);
392+
assertThat(executionInfo.isCrossClusterSearch(), is(true));
393+
long overallTookMillis = executionInfo.overallTook().millis();
394+
assertThat(overallTookMillis, greaterThanOrEqualTo(0L));
395+
396+
EsqlExecutionInfo.Cluster remoteCluster = executionInfo.getCluster(REMOTE_CLUSTER_1);
397+
assertClusterMetadataSkipped(remoteCluster, overallTookMillis, "missing,logs-*");
398+
assertThat(remoteCluster.getFailures(), hasSize(1));
399+
var fail = remoteCluster.getFailures().get(0);
400+
assertThat(fail.getCause().getMessage(), containsString("no such index [missing]"));
401+
}
402+
// TODO: for now, these fail, but in the future may be skipped instead
403+
// Remote index missing
404+
VerificationException e = expectThrows(
405+
VerificationException.class,
406+
() -> runQuery("from cluster-a:missing", randomBoolean(), filter).close()
407+
);
408+
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
409+
// Wildcard index missing
410+
e = expectThrows(VerificationException.class, () -> runQuery("from cluster-a:missing*", randomBoolean(), filter).close());
411+
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing*]"));
412+
}
413+
}
414+
355415
private void checkRemoteFailures() {
356416
for (var filter : List.of(
357417
new RangeQueryBuilder("@timestamp").from("2024-01-01").to("now"),

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlCCSUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,15 @@ static void updateExecutionInfoWithClustersWithNoMatchingIndices(
221221
"Unknown index [%s]",
222222
(c.equals(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY) ? indexExpression : c + ":" + indexExpression)
223223
);
224-
if (executionInfo.isSkipUnavailable(c) == false) {
224+
if (executionInfo.isSkipUnavailable(c) == false || filter != null) {
225225
if (fatalErrorMessage == null) {
226226
fatalErrorMessage = error;
227227
} else {
228228
fatalErrorMessage += "; " + error;
229229
}
230230
}
231231
if (filter == null) {
232-
// We check for filter since the filter may be the reason why the index is missing, and then it's ok
232+
// We check for filter since the filter may be the reason why the index is missing, and then we don't want to mark yet
233233
markClusterWithFinalStateAndNoShards(
234234
executionInfo,
235235
c,

0 commit comments

Comments
 (0)