Fix queries with missing index, skip_unavailable and filters (#130344)

* Fix queries with missing index, skip_unavailable and filters
This commit is contained in:
Stanislav Malyshev 2025-06-30 17:55:17 -06:00 committed by GitHub
parent 8bd4645eff
commit 3b13977343
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 4 deletions

View File

@ -0,0 +1,5 @@
pr: 130344
summary: "Fix queries with missing index, `skip_unavailable` and filters"
area: ES|QL
type: bug
issues: []

View File

@ -313,13 +313,13 @@ public class CrossClusterQueryWithFiltersIT extends AbstractCrossClusterTestCase
new RangeQueryBuilder("@timestamp").from("2025-01-01").to("now")
)) {
count++;
// Local index missing
// Remote index missing
VerificationException e = expectThrows(
VerificationException.class,
() -> runQuery("from cluster-a:missing", randomBoolean(), filter).close()
);
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
// Local index missing + wildcards
// Remote index missing + wildcards
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime RemoteException
var ie = expectThrows(
RemoteException.class,
@ -352,6 +352,66 @@ public class CrossClusterQueryWithFiltersIT extends AbstractCrossClusterTestCase
}
}
public void testFilterWithMissingRemoteIndexSkipUnavailable() {
int docsTest1 = 50;
int docsTest2 = 30;
int localShards = randomIntBetween(1, 5);
int remoteShards = randomIntBetween(1, 5);
populateDateIndex(LOCAL_CLUSTER, LOCAL_INDEX, localShards, docsTest1, "2024-11-26");
populateDateIndex(REMOTE_CLUSTER_1, REMOTE_INDEX, remoteShards, docsTest2, "2023-11-26");
setSkipUnavailable(REMOTE_CLUSTER_1, true);
int count = 0;
for (var filter : List.of(
new RangeQueryBuilder("@timestamp").from("2023-01-01").to("now"),
new RangeQueryBuilder("@timestamp").from("2024-01-01").to("now"),
new RangeQueryBuilder("@timestamp").from("2025-01-01").to("now")
)) {
count++;
try (EsqlQueryResponse resp = runQuery("from cluster-a:missing,logs-1", randomBoolean(), filter)) {
List<List<Object>> values = getValuesList(resp);
assertThat(values, hasSize(count > 2 ? 0 : docsTest1));
EsqlExecutionInfo executionInfo = resp.getExecutionInfo();
assertNotNull(executionInfo);
assertThat(executionInfo.isCrossClusterSearch(), is(true));
long overallTookMillis = executionInfo.overallTook().millis();
assertThat(overallTookMillis, greaterThanOrEqualTo(0L));
EsqlExecutionInfo.Cluster remoteCluster = executionInfo.getCluster(REMOTE_CLUSTER_1);
assertClusterMetadataSkipped(remoteCluster, overallTookMillis, "missing");
assertThat(remoteCluster.getFailures(), hasSize(1));
var fail = remoteCluster.getFailures().get(0);
assertThat(fail.getCause().getMessage(), containsString("Unknown index [cluster-a:missing]"));
}
try (EsqlQueryResponse resp = runQuery("from cluster-a:missing,cluster-a:logs-*", randomBoolean(), filter)) {
List<List<Object>> values = getValuesList(resp);
assertThat(values, hasSize(0));
EsqlExecutionInfo executionInfo = resp.getExecutionInfo();
assertNotNull(executionInfo);
assertThat(executionInfo.isCrossClusterSearch(), is(true));
long overallTookMillis = executionInfo.overallTook().millis();
assertThat(overallTookMillis, greaterThanOrEqualTo(0L));
EsqlExecutionInfo.Cluster remoteCluster = executionInfo.getCluster(REMOTE_CLUSTER_1);
assertClusterMetadataSkipped(remoteCluster, overallTookMillis, "missing,logs-*");
assertThat(remoteCluster.getFailures(), hasSize(1));
var fail = remoteCluster.getFailures().get(0);
assertThat(fail.getCause().getMessage(), containsString("no such index [missing]"));
}
// TODO: for now, these fail, but in the future may be skipped instead
// Remote index missing
VerificationException e = expectThrows(
VerificationException.class,
() -> runQuery("from cluster-a:missing", randomBoolean(), filter).close()
);
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
// Wildcard index missing
e = expectThrows(VerificationException.class, () -> runQuery("from cluster-a:missing*", randomBoolean(), filter).close());
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing*]"));
}
}
private void checkRemoteFailures() {
for (var filter : List.of(
new RangeQueryBuilder("@timestamp").from("2024-01-01").to("now"),

View File

@ -221,7 +221,7 @@ public class EsqlCCSUtils {
"Unknown index [%s]",
(c.equals(RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY) ? indexExpression : c + ":" + indexExpression)
);
if (executionInfo.isSkipUnavailable(c) == false) {
if (executionInfo.isSkipUnavailable(c) == false || filter != null) {
if (fatalErrorMessage == null) {
fatalErrorMessage = error;
} else {
@ -229,7 +229,7 @@ public class EsqlCCSUtils {
}
}
if (filter == null) {
// We check for filter since the filter may be the reason why the index is missing, and then it's ok
// 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
markClusterWithFinalStateAndNoShards(
executionInfo,
c,