Skip to content

Commit 49f8e5c

Browse files
authored
ES|QL: Support STATS after FORK (#128745)
1 parent 47d1bd5 commit 49f8e5c

File tree

5 files changed

+112
-18
lines changed

5 files changed

+112
-18
lines changed

x-pack/plugin/esql/qa/server/multi-clusters/src/javaRestTest/java/org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
import static org.elasticsearch.xpack.esql.CsvTestUtils.isEnabled;
4747
import static org.elasticsearch.xpack.esql.CsvTestsDataLoader.ENRICH_SOURCE_INDICES;
4848
import static org.elasticsearch.xpack.esql.EsqlTestUtils.classpathResources;
49-
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.FORK_V6;
49+
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.FORK_V7;
5050
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS;
5151
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS_V2;
5252
import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS_V7;
@@ -132,7 +132,7 @@ protected void shouldSkipTest(String testName) throws IOException {
132132
assumeFalse("LOOKUP JOIN not yet supported in CCS", testCase.requiredCapabilities.contains(JOIN_LOOKUP_V12.capabilityName()));
133133
// Unmapped fields require a coorect capability response from every cluster, which isn't currently implemented.
134134
assumeFalse("UNMAPPED FIELDS not yet supported in CCS", testCase.requiredCapabilities.contains(UNMAPPED_FIELDS.capabilityName()));
135-
assumeFalse("FORK not yet supported in CCS", testCase.requiredCapabilities.contains(FORK_V6.capabilityName()));
135+
assumeFalse("FORK not yet supported in CCS", testCase.requiredCapabilities.contains(FORK_V7.capabilityName()));
136136
}
137137

138138
@Override

x-pack/plugin/esql/qa/testFixtures/src/main/resources/fork.csv-spec

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//
44

55
simpleFork
6-
required_capability: fork_v6
6+
required_capability: fork_v7
77

88
FROM employees
99
| FORK ( WHERE emp_no == 10001 )
@@ -18,7 +18,7 @@ emp_no:integer | _fork:keyword
1818
;
1919

2020
forkWithWhereSortAndLimit
21-
required_capability: fork_v6
21+
required_capability: fork_v7
2222

2323
FROM employees
2424
| FORK ( WHERE hire_date < "1985-03-01T00:00:00Z" | SORT first_name | LIMIT 5 )
@@ -38,7 +38,7 @@ emp_no:integer | first_name:keyword | _fork:keyword
3838
;
3939

4040
fiveFork
41-
required_capability: fork_v6
41+
required_capability: fork_v7
4242

4343
FROM employees
4444
| FORK ( WHERE emp_no == 10005 )
@@ -59,7 +59,7 @@ fork5 | 10001
5959
;
6060

6161
forkWithWhereSortDescAndLimit
62-
required_capability: fork_v6
62+
required_capability: fork_v7
6363

6464
FROM employees
6565
| FORK ( WHERE hire_date < "1985-03-01T00:00:00Z" | SORT first_name DESC | LIMIT 2 )
@@ -76,7 +76,7 @@ fork2 | 10087 | Xinglin
7676
;
7777

7878
forkWithCommonPrefilter
79-
required_capability: fork_v6
79+
required_capability: fork_v7
8080

8181
FROM employees
8282
| WHERE emp_no > 10050
@@ -94,7 +94,7 @@ fork2 | 10100
9494
;
9595

9696
forkWithSemanticSearchAndScore
97-
required_capability: fork_v6
97+
required_capability: fork_v7
9898
required_capability: semantic_text_field_caps
9999
required_capability: metadata_score
100100

@@ -114,7 +114,7 @@ fork2 | 6.093784261960139E18 | 2 | all we have to decide is w
114114
;
115115

116116
forkWithEvals
117-
required_capability: fork_v6
117+
required_capability: fork_v7
118118

119119
FROM employees
120120
| FORK (WHERE emp_no == 10048 OR emp_no == 10081 | EVAL x = "abc" | EVAL y = 1)
@@ -131,7 +131,7 @@ fork2 | 10087 | def | null | 2
131131
;
132132

133133
forkWithStats
134-
required_capability: fork_v6
134+
required_capability: fork_v7
135135

136136
FROM employees
137137
| FORK (WHERE emp_no == 10048 OR emp_no == 10081)
@@ -152,7 +152,7 @@ fork4 | null | 100 | 10001 | null
152152
;
153153

154154
forkWithDissect
155-
required_capability: fork_v6
155+
required_capability: fork_v7
156156

157157
FROM employees
158158
| WHERE emp_no == 10048 OR emp_no == 10081
@@ -172,7 +172,7 @@ fork2 | 10081 | Rosen | 10081 | null | Zhongwei
172172
;
173173

174174
forkWithMixOfCommands
175-
required_capability: fork_v6
175+
required_capability: fork_v7
176176

177177
FROM employees
178178
| WHERE emp_no == 10048 OR emp_no == 10081
@@ -197,7 +197,7 @@ fork4 | 10081 | abc | aaa | null | null
197197
;
198198

199199
forkWithFiltersOnConstantValues
200-
required_capability: fork_v6
200+
required_capability: fork_v7
201201

202202
FROM employees
203203
| EVAL z = 1
@@ -218,7 +218,7 @@ fork3 | null | 100 | 10100 | 10001
218218
;
219219

220220
forkWithUnsupportedAttributes
221-
required_capability: fork_v6
221+
required_capability: fork_v7
222222

223223
FROM heights
224224
| FORK (SORT description DESC | LIMIT 1 | EVAL x = length(description) )
@@ -232,7 +232,7 @@ Medium Height | null | null | fork2
232232
;
233233

234234
forkAfterLookupJoin
235-
required_capability: fork_v6
235+
required_capability: fork_v7
236236

237237
FROM employees
238238
| EVAL language_code = languages
@@ -253,7 +253,7 @@ fork3 | 10081 | 2 | Klingon
253253
;
254254

255255
forkBeforeLookupJoin
256-
required_capability: fork_v6
256+
required_capability: fork_v7
257257

258258
FROM employees
259259
| EVAL language_code = languages
@@ -272,3 +272,64 @@ fork2 | 10081 | 2 | French
272272
fork2 | 10087 | 5 | null
273273
fork3 | 10081 | 2 | French
274274
;
275+
276+
277+
forkBeforeStats
278+
required_capability: fork_v7
279+
280+
FROM employees
281+
| WHERE emp_no == 10048 OR emp_no == 10081
282+
| FORK ( EVAL a = CONCAT(first_name, " ", emp_no::keyword, " ", last_name)
283+
| DISSECT a "%{x} %{y} %{z}"
284+
| EVAL y = y::keyword )
285+
( STATS x = COUNT(*)::keyword, y = MAX(emp_no)::keyword, z = MIN(emp_no)::keyword )
286+
( SORT emp_no ASC | LIMIT 2 | EVAL x = last_name )
287+
( EVAL x = "abc" | EVAL y = "aaa" )
288+
| STATS c = count(*), m = max(_fork)
289+
;
290+
291+
c:long | m:keyword
292+
7 | fork4
293+
;
294+
295+
forkBeforeStatsWithWhere
296+
required_capability: fork_v7
297+
298+
FROM employees
299+
| WHERE emp_no == 10048 OR emp_no == 10081
300+
| FORK ( EVAL a = CONCAT(first_name, " ", emp_no::keyword, " ", last_name)
301+
| DISSECT a "%{x} %{y} %{z}"
302+
| EVAL y = y::keyword )
303+
( STATS x = COUNT(*)::keyword, y = MAX(emp_no)::keyword, z = MIN(emp_no)::keyword )
304+
( SORT emp_no ASC | LIMIT 2 | EVAL x = last_name )
305+
( EVAL x = "abc" | EVAL y = "aaa" )
306+
| STATS a = count(*) WHERE _fork == "fork1",
307+
b = max(_fork)
308+
;
309+
310+
a:long | b:keyword
311+
2 | fork4
312+
;
313+
314+
forkBeforeStatsByWithWhere
315+
required_capability: fork_v7
316+
317+
FROM employees
318+
| WHERE emp_no == 10048 OR emp_no == 10081
319+
| FORK ( EVAL a = CONCAT(first_name, " ", emp_no::keyword, " ", last_name)
320+
| DISSECT a "%{x} %{y} %{z}"
321+
| EVAL y = y::keyword )
322+
( STATS x = COUNT(*)::keyword, y = MAX(emp_no)::keyword, z = MIN(emp_no)::keyword )
323+
( SORT emp_no ASC | LIMIT 2 | EVAL x = last_name )
324+
( EVAL x = "abc" | EVAL y = "aaa" )
325+
| STATS a = count(*) WHERE emp_no > 10000,
326+
b = max(x) WHERE _fork == "fork1" BY _fork
327+
| SORT _fork
328+
;
329+
330+
a:long | b:keyword | _fork:keyword
331+
2 | Zhongwei | fork1
332+
0 | null | fork2
333+
2 | null | fork3
334+
2 | null | fork4
335+
;

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,39 @@ public void testWithStatsSimple() {
588588
}
589589
}
590590

591+
public void testWithStatsAfterFork() {
592+
var query = """
593+
FROM test
594+
| FORK ( WHERE content:"fox" | EVAL a = 1)
595+
( WHERE content:"cat" | EVAL b = 2 )
596+
( WHERE content:"dog" | EVAL c = 3 )
597+
| STATS c = count(*)
598+
""";
599+
try (var resp = run(query)) {
600+
assertColumnNames(resp.columns(), List.of("c"));
601+
assertColumnTypes(resp.columns(), List.of("long"));
602+
Iterable<Iterable<Object>> expectedValues = List.of(List.of(7L));
603+
assertValues(resp.values(), expectedValues);
604+
}
605+
}
606+
607+
public void testWithStatsWithWhereAfterFork() {
608+
var query = """
609+
FROM test
610+
| FORK ( WHERE content:"fox" | EVAL a = 1)
611+
( WHERE content:"cat" | EVAL b = 2 )
612+
( WHERE content:"dog" | EVAL c = 3 )
613+
| STATS c = count(*) WHERE _fork == "fork1"
614+
""";
615+
try (var resp = run(query)) {
616+
assertColumnNames(resp.columns(), List.of("c"));
617+
assertColumnTypes(resp.columns(), List.of("long"));
618+
619+
Iterable<Iterable<Object>> expectedValues = List.of(List.of(2L));
620+
assertValues(resp.values(), expectedValues);
621+
}
622+
}
623+
591624
public void testWithConditionOnForkField() {
592625
var query = """
593626
FROM test

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ public enum Cap {
10351035
/**
10361036
* Support streaming of sub plan results
10371037
*/
1038-
FORK_V6(Build.current().isSnapshot()),
1038+
FORK_V7(Build.current().isSnapshot()),
10391039

10401040
/**
10411041
* Support for the {@code leading_zeros} named parameter.

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public final void test() throws Throwable {
318318
);
319319
assumeFalse(
320320
"CSV tests cannot currently handle FORK",
321-
testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.FORK_V6.capabilityName())
321+
testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.FORK_V7.capabilityName())
322322
);
323323
assumeFalse(
324324
"CSV tests cannot currently handle multi_match function that depends on Lucene",

0 commit comments

Comments
 (0)