Skip to content

Commit 8771dfc

Browse files
Merge branch 'main' of github.com:elastic/elasticsearch into inference-eis-acl
2 parents 56e44b0 + 7e43605 commit 8771dfc

File tree

148 files changed

+6004
-1229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

148 files changed

+6004
-1229
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/*.interp li
1111
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer*.java linguist-generated=true
1212
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser*.java linguist-generated=true
1313
x-pack/plugin/esql/src/main/generated/** linguist-generated=true
14+
x-pack/plugin/esql/src/main/generated-src/** linguist-generated=true
1415

1516
# ESQL functions docs are autogenerated. More information at `docs/reference/esql/functions/README.md`
1617
docs/reference/esql/functions/*/** linguist-generated=true

benchmarks/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ exit
126126
Grab the async profiler from https://github.com/jvm-profiling-tools/async-profiler
127127
and run `prof async` like so:
128128
```
129-
gradlew -p benchmarks/ run --args 'LongKeyedBucketOrdsBenchmark.multiBucket -prof "async:libPath=/home/nik9000/Downloads/tmp/async-profiler-1.8.3-linux-x64/build/libasyncProfiler.so;dir=/tmp/prof;output=flamegraph"'
129+
gradlew -p benchmarks/ run --args 'LongKeyedBucketOrdsBenchmark.multiBucket -prof "async:libPath=/home/nik9000/Downloads/async-profiler-3.0-29ee888-linux-x64/lib/libasyncProfiler.so;dir=/tmp/prof;output=flamegraph"'
130130
```
131131

132+
Note: As of January 2025 the latest release of async profiler doesn't work
133+
with our JDK but the nightly is fine.
134+
132135
If you are on Mac, this'll warn you that you downloaded the shared library from
133136
the internet. You'll need to go to settings and allow it to run.
134137

benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateTrunc;
3939
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs;
4040
import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvMin;
41+
import org.elasticsearch.xpack.esql.expression.function.scalar.nulls.Coalesce;
4142
import org.elasticsearch.xpack.esql.expression.function.scalar.string.RLike;
4243
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add;
4344
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.Equals;
@@ -96,6 +97,9 @@ public class EvalBenchmark {
9697
"add_double",
9798
"case_1_eager",
9899
"case_1_lazy",
100+
"coalesce_2_noop",
101+
"coalesce_2_eager",
102+
"coalesce_2_lazy",
99103
"date_trunc",
100104
"equal_to_const",
101105
"long_equal_to_long",
@@ -142,8 +146,34 @@ private static EvalOperator.ExpressionEvaluator evaluator(String operation) {
142146
lhs = new Add(Source.EMPTY, lhs, new Literal(Source.EMPTY, 1L, DataType.LONG));
143147
rhs = new Add(Source.EMPTY, rhs, new Literal(Source.EMPTY, 1L, DataType.LONG));
144148
}
145-
yield EvalMapper.toEvaluator(FOLD_CONTEXT, new Case(Source.EMPTY, condition, List.of(lhs, rhs)), layout(f1, f2))
146-
.get(driverContext);
149+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
150+
FOLD_CONTEXT,
151+
new Case(Source.EMPTY, condition, List.of(lhs, rhs)),
152+
layout(f1, f2)
153+
).get(driverContext);
154+
String desc = operation.endsWith("lazy") ? "CaseLazyEvaluator" : "CaseEagerEvaluator";
155+
if (evaluator.toString().contains(desc) == false) {
156+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
157+
}
158+
yield evaluator;
159+
}
160+
case "coalesce_2_noop", "coalesce_2_eager", "coalesce_2_lazy" -> {
161+
FieldAttribute f1 = longField();
162+
FieldAttribute f2 = longField();
163+
Expression lhs = f1;
164+
if (operation.endsWith("lazy")) {
165+
lhs = new Add(Source.EMPTY, lhs, new Literal(Source.EMPTY, 1L, DataType.LONG));
166+
}
167+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
168+
FOLD_CONTEXT,
169+
new Coalesce(Source.EMPTY, lhs, List.of(f2)),
170+
layout(f1, f2)
171+
).get(driverContext);
172+
String desc = operation.endsWith("lazy") ? "CoalesceLazyEvaluator" : "CoalesceEagerEvaluator";
173+
if (evaluator.toString().contains(desc) == false) {
174+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
175+
}
176+
yield evaluator;
147177
}
148178
case "date_trunc" -> {
149179
FieldAttribute timestamp = new FieldAttribute(
@@ -260,6 +290,38 @@ private static void checkExpected(String operation, Page actual) {
260290
}
261291
}
262292
}
293+
case "coalesce_2_noop" -> {
294+
LongVector f1 = actual.<LongBlock>getBlock(0).asVector();
295+
LongVector result = actual.<LongBlock>getBlock(2).asVector();
296+
for (int i = 0; i < BLOCK_LENGTH; i++) {
297+
long expected = f1.getLong(i);
298+
if (result.getLong(i) != expected) {
299+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
300+
}
301+
}
302+
}
303+
case "coalesce_2_eager" -> {
304+
LongBlock f1 = actual.<LongBlock>getBlock(0);
305+
LongVector f2 = actual.<LongBlock>getBlock(1).asVector();
306+
LongVector result = actual.<LongBlock>getBlock(2).asVector();
307+
for (int i = 0; i < BLOCK_LENGTH; i++) {
308+
long expected = i % 5 == 0 ? f2.getLong(i) : f1.getLong(f1.getFirstValueIndex(i));
309+
if (result.getLong(i) != expected) {
310+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
311+
}
312+
}
313+
}
314+
case "coalesce_2_lazy" -> {
315+
LongBlock f1 = actual.<LongBlock>getBlock(0);
316+
LongVector f2 = actual.<LongBlock>getBlock(1).asVector();
317+
LongVector result = actual.<LongBlock>getBlock(2).asVector();
318+
for (int i = 0; i < BLOCK_LENGTH; i++) {
319+
long expected = i % 5 == 0 ? f2.getLong(i) : f1.getLong(f1.getFirstValueIndex(i)) + 1;
320+
if (result.getLong(i) != expected) {
321+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
322+
}
323+
}
324+
}
263325
case "date_trunc" -> {
264326
LongVector v = actual.<LongBlock>getBlock(1).asVector();
265327
long oneDay = TimeValue.timeValueHours(24).millis();
@@ -304,7 +366,7 @@ private static void checkExpected(String operation, Page actual) {
304366
}
305367
}
306368
}
307-
default -> throw new UnsupportedOperationException();
369+
default -> throw new UnsupportedOperationException(operation);
308370
}
309371
}
310372

@@ -324,7 +386,7 @@ private static Page page(String operation) {
324386
}
325387
yield new Page(builder.build());
326388
}
327-
case "case_1_eager", "case_1_lazy" -> {
389+
case "case_1_eager", "case_1_lazy", "coalesce_2_noop" -> {
328390
var f1 = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
329391
var f2 = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
330392
for (int i = 0; i < BLOCK_LENGTH; i++) {
@@ -333,6 +395,19 @@ private static Page page(String operation) {
333395
}
334396
yield new Page(f1.build(), f2.build());
335397
}
398+
case "coalesce_2_eager", "coalesce_2_lazy" -> {
399+
var f1 = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
400+
var f2 = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
401+
for (int i = 0; i < BLOCK_LENGTH; i++) {
402+
if (i % 5 == 0) {
403+
f1.appendNull();
404+
} else {
405+
f1.appendLong(i);
406+
}
407+
f2.appendLong(-i);
408+
}
409+
yield new Page(f1.build(), f2.build());
410+
}
336411
case "long_equal_to_long" -> {
337412
var lhs = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
338413
var rhs = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);

docs/changelog/118122.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 118122
2+
summary: "ES|QL: Partial result on demand for async queries"
3+
area: ES|QL
4+
type: enhancement
5+
issues: []

docs/changelog/120645.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 120645
2+
summary: Esql Support date nanos on date diff function
3+
area: ES|QL
4+
type: enhancement
5+
issues:
6+
- 109999

docs/reference/esql/esql-across-clusters.asciidoc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ Which returns:
210210
{
211211
"is_running": false,
212212
"took": 42, <1>
213+
"is_partial": false, <7>
213214
"columns" : [
214215
{
215216
"name" : "COUNT(http.response.status_code)",
@@ -275,8 +276,9 @@ Which returns:
275276
<2> This section of counters shows all possible cluster search states and how many cluster
276277
searches are currently in that state. The clusters can have one of the following statuses: *running*,
277278
*successful* (searches on all shards were successful), *skipped* (the search
278-
failed on a cluster marked with `skip_unavailable`=`true`) or *failed* (the search
279-
failed on a cluster marked with `skip_unavailable`=`false`).
279+
failed on a cluster marked with `skip_unavailable`=`true`), *failed* (the search
280+
failed on a cluster marked with `skip_unavailable`=`false`) or **partial** (the search was
281+
<<esql-async-query-stop-api, interrupted>> before finishing).
280282
<3> The `_clusters/details` section shows metadata about the search on each cluster.
281283
<4> If you included indices from the local cluster you sent the request to in your {ccs},
282284
it is identified as "(local)".
@@ -285,6 +287,8 @@ which clusters have slower response times than others.
285287
<6> The shard details for the search on that cluster, including a count of shards that were
286288
skipped due to the can-match phase results. Shards are skipped when they cannot have any matching data
287289
and therefore are not included in the full ES|QL query.
290+
<7> The `is_partial` field is set to `true` if the search has partial results for any reason,
291+
for example if it was interrupted before finishing using the <<esql-async-query-stop-api,async query stop API>>.
288292

289293

290294
The cross-cluster metadata can be used to determine whether any data came back from a cluster.
@@ -314,6 +318,7 @@ Which returns:
314318
{
315319
"is_running": false,
316320
"took": 55,
321+
"is_partial": false,
317322
"columns": [
318323
... // not shown
319324
],

docs/reference/esql/esql-apis.asciidoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ overview of {esql} and related tutorials, see <<esql>>.
1717
* <<esql-async-query-api>>
1818
* <<esql-async-query-get-api>>
1919
* <<esql-async-query-delete-api>>
20+
* <<esql-async-query-stop-api>>
2021

2122

2223
include::esql-query-api.asciidoc[]
@@ -26,3 +27,5 @@ include::esql-async-query-api.asciidoc[]
2627
include::esql-async-query-get-api.asciidoc[]
2728

2829
include::esql-async-query-delete-api.asciidoc[]
30+
31+
include::esql-async-query-stop-api.asciidoc[]

docs/reference/esql/esql-async-query-api.asciidoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,10 @@ API>> to get the current status and available results for the query.
170170
(Boolean)
171171
If `true`, the query request is still executing.
172172
--
173+
174+
`is_partial`::
175+
+
176+
--
177+
(Boolean)
178+
If `true`, the query has partial results - for example, as a result of using the <<esql-async-query-stop-api, async query stop API>>.
179+
--
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[[esql-async-query-stop-api]]
2+
=== {esql} async query stop API
3+
++++
4+
<titleabbrev>{esql} async query stop API</titleabbrev>
5+
++++
6+
7+
.New API reference
8+
[sidebar]
9+
--
10+
For the most up-to-date API details, refer to {api-es}/group/endpoint-esql[ES|QL APIs].
11+
--
12+
13+
The <<esql,{esql}>> async query stop API is used to manually stop an async query. Once the stop command is issued,
14+
the query stops processing new data and returns the results that have been already processed. Note that due to the pipelined
15+
nature of {esql} queries, the stop operation is not immediate and may take time to return results.
16+
17+
The results are returned in <<esql-query-api-response-body,the same format>> as the
18+
<<esql-async-query-get-api,{esql} async query get API>>.
19+
If the query has been finished by the time the stop command is issued, the results are returned immediately.
20+
21+
If the query processing has not finished by the time the stop command is issued, the response will have the `is_partial`
22+
field set to `true`.
23+
24+
[source,console]
25+
----
26+
POST /query/async/FkpMRkJGS1gzVDRlM3g4ZzMyRGlLbkEaTXlJZHdNT09TU2VTZVBoNDM3cFZMUToxMDM=/stop
27+
----
28+
// TEST[skip: no access to query ID]
29+
30+
[[esql-async-query-stop-api-request]]
31+
==== {api-request-title}
32+
33+
`POST /_query/async/<query_id>/stop`
34+
35+
[[esql-async-query-stop-api-prereqs]]
36+
==== {api-prereq-title}
37+
38+
* If the {es} {security-features} are enabled, only the authenticated user that submitted the original query request
39+
can stop the query.
40+
41+
[[esql-async-query-stop-api-path-params]]
42+
==== {api-path-parms-title}
43+
44+
`<query_id>`::
45+
(Required, string)
46+
Identifier for the query to stop.
47+
+
48+
A query ID is provided in the <<esql-async-query-api,{esql} async query API>>'s
49+
response for a query that does not complete in the awaited time.

docs/reference/esql/esql-rest.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ Which returns:
193193
----
194194
{
195195
"took": 28,
196+
"is_partial": false,
196197
"columns": [
197198
{"name": "author", "type": "text"},
198199
{"name": "name", "type": "text"},

0 commit comments

Comments
 (0)