Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/changelog/135601.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pr: 135601
summary: ES|QL Empty index resolution
area: ES|QL
type: breaking
issues: []
breaking:
title: ES|QL Empty index resolution
area: ES|QL
details: Changes index resolution so that `FROM empty*` resolves to empty set of indices (opposed to error today)
and becomes consistent with `GET /empty*/_search`.
impact: Makes a valid query check a bit more permissive in case when pattern is resolved to empty set of indices.
notable: false
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ public void testIndicesDontExist() throws IOException {
assertThat(e.getMessage(), containsString("verification_exception"));
assertThat(e.getMessage(), anyOf(containsString("Unknown index [foo]"), containsString("Unknown index [remote_cluster:foo]")));

e = expectThrows(ResponseException.class, () -> runEsql(timestampFilter("gte", "2020-01-01").query(from("foo*"))));
assertEquals(400, e.getResponse().getStatusLine().getStatusCode());
assertThat(e.getMessage(), containsString("verification_exception"));
assertThat(e.getMessage(), anyOf(containsString("Unknown index [foo*]"), containsString("Unknown index [remote_cluster:foo*]")));

e = expectThrows(ResponseException.class, () -> runEsql(timestampFilter("gte", "2020-01-01").query("FROM foo, test1")));
assertEquals(404, e.getResponse().getStatusLine().getStatusCode());
assertThat(e.getMessage(), containsString("index_not_found_exception"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,20 @@ public void testResolvesExclusionPattern() {
assertOk(response);
assertResultConcreteIndices(response, "index-1");// excludes pattern from pattern
}
expectThrows(
VerificationException.class,
containsString("Unknown index [index-*,-*]"),
() -> run(syncEsqlQueryRequest().query("FROM index-*,-* METADATA _index")) // exclude all resolves to empty
);
try (var response = run(syncEsqlQueryRequest().query("FROM index-*,-* METADATA _index"))) {
assertOk(response);
assertResultConcreteIndices(response);// exclude all resolves to empty
}
}

public void testDoesNotResolveEmptyPattern() {
public void testResolveEmptyPattern() {
assertAcked(client().admin().indices().prepareCreate("data"));
indexRandom(true, "data", 1);

expectThrows(
VerificationException.class,
containsString("Unknown index [index-*]"),
() -> run(syncEsqlQueryRequest().query("FROM index-* METADATA _index"))
);

try (var response = run(syncEsqlQueryRequest().query("FROM index-* METADATA _index"))) {
assertOk(response);
assertResultConcreteIndices(response);
}
try (var response = run(syncEsqlQueryRequest().query("FROM data,index-* METADATA _index"))) {
assertOk(response);
assertResultConcreteIndices(response, "data");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public static IndexResolution invalid(String invalid) {
return new IndexResolution(null, invalid, Set.of(), Map.of());
}

public static IndexResolution empty(String indexPattern) {
return IndexResolution.valid(new EsIndex(indexPattern, Map.of(), Map.of()));
}

public static IndexResolution notFound(String name) {
Objects.requireNonNull(name, "name must not be null");
return invalid("Unknown index [" + name + "]");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ private PreAnalysisResult receiveLookupIndexResolution(
// If the index resolution is invalid, don't bother with the rest of the analysis
return result.addLookupIndexResolution(index, lookupIndexResolution);
}
if (lookupIndexResolution.get().concreteIndices().isEmpty()) {
// require non empty lookup index
return result.addLookupIndexResolution(index, IndexResolution.notFound(lookupIndexResolution.get().name()));
}
if (executionInfo.getClusters().isEmpty() || executionInfo.isCrossClusterSearch() == false) {
// Local only case, still do some checks, since we moved analysis checks here
if (lookupIndexResolution.get().indexNameWithModes().isEmpty()) {
Expand Down Expand Up @@ -696,9 +700,7 @@ private void preAnalyzeMainIndices(
String indexExpressionToResolve = EsqlCCSUtils.createIndexExpressionFromAvailableClusters(executionInfo);
if (indexExpressionToResolve.isEmpty()) {
// if this was a pure remote CCS request (no local indices) and all remotes are offline, return an empty IndexResolution
listener.onResponse(
result.withIndices(IndexResolution.valid(new EsIndex(preAnalysis.indexPattern().indexPattern(), Map.of(), Map.of())))
);
listener.onResponse(result.withIndices(IndexResolution.empty(preAnalysis.indexPattern().indexPattern())));
} else {
indexResolver.resolveAsMergedMapping(
indexExpressionToResolve,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public static IndexResolution mergedMappings(String indexPattern, FieldsInfo fie
assert ThreadPool.assertCurrentThreadPool(ThreadPool.Names.SEARCH_COORDINATION); // too expensive to run this on a transport worker
int numberOfIndices = fieldsInfo.caps.getIndexResponses().size();
if (numberOfIndices == 0) {
return IndexResolution.notFound(indexPattern);
return IndexResolution.empty(indexPattern);
}

// For each field name, store a list of the field caps responses from each index
Expand Down