From 6dd6c4f986b029b22bcc5accfdc433a7293c2dc3 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Wed, 27 Aug 2025 17:23:31 +0200 Subject: [PATCH 1/4] Don't duplicate Limit on left InlineJoin ...as this reduces the data the (inline) aggs run on, which is wrong. --- .../src/main/resources/inlinestats.csv-spec | 30 +++++++- .../logical/PushDownAndCombineLimits.java | 3 +- .../optimizer/LogicalPlanOptimizerTests.java | 75 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec index d0381725d5c34..236c235f9d6f9 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec @@ -51,6 +51,33 @@ emp_no:integer | languages:integer | max_lang:integer | gender:keyword 10014 | 5 | 5 | null ; +maxOfIntByKeywordLimit1Aggd +required_capability: inlinestats_v10 + +FROM employees +| KEEP emp_no, languages, gender +| INLINESTATS max_lang = MAX(languages) BY gender +| LIMIT 1 +| STATS v = VALUES(max_lang) +; + +v:integer +5 +; + +simpleAvg +required_capability: inlinestats_v10 + +FROM employees +| INLINESTATS a = AVG(salary) +| LIMIT 2 +| KEEP a; + +a:double +48248.55 +48248.55 +; + maxOfLongByKeyword required_capability: inlinestats_v10 @@ -247,7 +274,8 @@ emp_no:integer |avg_worked_seconds:long|avg_avg_worked_seconds:double|languages: ; // TODO: INLINESTATS unit test needed for this one -pushDownSort_To_LeftSideOnly +// https://github.com/elastic/elasticsearch/issues/113727 +pushDownSort_To_LeftSideOnly-Ignore required_capability: inlinestats_v10 from employees diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineLimits.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineLimits.java index 7bad50abd46de..041e52d1df56d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineLimits.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineLimits.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.plan.logical.RegexExtract; import org.elasticsearch.xpack.esql.plan.logical.UnaryPlan; import org.elasticsearch.xpack.esql.plan.logical.inference.InferencePlan; +import org.elasticsearch.xpack.esql.plan.logical.join.InlineJoin; import org.elasticsearch.xpack.esql.plan.logical.join.Join; import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes; @@ -64,7 +65,7 @@ public LogicalPlan rule(Limit limit, LogicalOptimizerContext ctx) { } } } - } else if (limit.child() instanceof Join join && join.config().type() == JoinTypes.LEFT) { + } else if (limit.child() instanceof Join join && join.config().type() == JoinTypes.LEFT && join instanceof InlineJoin == false) { // Left joins increase the number of rows if any join key has multiple matches from the right hand side. // Therefore, we cannot simply push down the limit - but we can add another limit before the join. // To avoid repeating this infinitely, we have to set duplicated = true. diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index a780d483c74ae..96e66faf871c6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -6005,6 +6005,81 @@ public void testInlinestatsWithRow() { ); } + /* + * EsqlProject[[a{r}#4]] + * \_Limit[2[INTEGER],false] + * \_InlineJoin[LEFT,[],[],[]] + * |_EsRelation[test][_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, ge..] + * \_Project[[a{r}#4]] + * \_Eval[[$$SUM$a$0{r$}#17 / $$COUNT$a$1{r$}#18 AS a#4]] + * \_Aggregate[[],[SUM(salary{f}#11,true[BOOLEAN],compensated[KEYWORD]) AS $$SUM$a$0#17, + * COUNT(salary{f}#11,true[BOOLEAN]) AS $$COUNT$a$1#18]] + * \_StubRelation[[_meta_field{f}#12, emp_no{f}#6, first_name{f}#7, gender{f}#8, hire_date{f}#13, job{f}#14, job.raw{f}#15, + * languages{f}#9, last_name{f}#10, long_noidx{f}#16, salary{f}#11]] + */ + public void testInlinestatsWithLimit() { + var query = """ + FROM employees + | INLINESTATS a = AVG(salary) + | LIMIT 2 + | KEEP a + """; + if (releaseBuildForInlinestats(query)) { + return; + } + var plan = optimizedPlan(query); + + var project = as(plan, EsqlProject.class); + assertThat(Expressions.names(project.projections()), is(List.of("a"))); + var limit = asLimit(project.child(), 2, false); + var inlineJoin = as(limit.child(), InlineJoin.class); + // Left + var relation = as(inlineJoin.left(), EsRelation.class); + // Right + var rightProject = as(inlineJoin.right(), Project.class); + assertThat(Expressions.names(rightProject.projections()), contains("a")); + var eval = as(rightProject.child(), Eval.class); + assertThat(Expressions.names(eval.fields()), is(List.of("a"))); + var agg = as(eval.child(), Aggregate.class); + var stub = as(agg.child(), StubRelation.class); + } + + /* + * Limit[10000[INTEGER],false] + * \_Aggregate[[],[VALUES(max_lang{r}#7,true[BOOLEAN]) AS v#11]] + * \_Limit[1[INTEGER],false] + * \_InlineJoin[LEFT,[gender{f}#14],[gender{f}#14],[gender{r}#14]] + * |_EsqlProject[[emp_no{f}#12, languages{f}#15, gender{f}#14]] + * | \_EsRelation[test][_meta_field{f}#18, emp_no{f}#12, first_name{f}#13, ..] + * \_Aggregate[[gender{f}#14],[MAX(languages{f}#15,true[BOOLEAN]) AS max_lang#7, gender{f}#14]] + * \_StubRelation[[emp_no{f}#12, languages{f}#15, gender{f}#14]] + */ + public void testInlinestatsWithLimitAndAgg() { + var query = """ + FROM employees + | KEEP emp_no, languages, gender + | INLINESTATS max_lang = MAX(languages) BY gender + | LIMIT 1 + | STATS v = VALUES(max_lang) + """; + if (releaseBuildForInlinestats(query)) { + return; + } + var plan = optimizedPlan(query); + + var limit = asLimit(plan, 10000, false); + var aggregate = as(limit.child(), Aggregate.class); + assertThat(Expressions.names(aggregate.aggregates()), is(List.of("v"))); + var innerLimit = asLimit(aggregate.child(), 1, false); + var inlineJoin = as(innerLimit.child(), InlineJoin.class); + // Left + var project = as(inlineJoin.left(), EsqlProject.class); + var relation = as(project.child(), EsRelation.class); + // Right + var agg = as(inlineJoin.right(), Aggregate.class); + var stub = as(agg.child(), StubRelation.class); + } + /** * Expects * From 4aeca518eab095f3ba124a9d225607de47636c08 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Wed, 27 Aug 2025 18:02:24 +0200 Subject: [PATCH 2/4] inlinestats_v10 to inlinestats_v11 bump --- .../xpack/esql/ccq/MultiClusterSpecIT.java | 4 +- .../src/main/resources/inlinestats.csv-spec | 260 +++++++++--------- .../xpack/esql/action/EsqlCapabilities.java | 2 +- .../xpack/esql/analysis/AnalyzerTests.java | 2 +- .../logical/PropagateInlineEvalsTests.java | 4 +- .../esql/session/FieldNameUtilsTests.java | 36 +-- 6 files changed, 154 insertions(+), 154 deletions(-) diff --git a/x-pack/plugin/esql/qa/server/multi-clusters/src/javaRestTest/java/org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java b/x-pack/plugin/esql/qa/server/multi-clusters/src/javaRestTest/java/org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java index 9e1ed7417efe6..4b90aa1a69c80 100644 --- a/x-pack/plugin/esql/qa/server/multi-clusters/src/javaRestTest/java/org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java +++ b/x-pack/plugin/esql/qa/server/multi-clusters/src/javaRestTest/java/org/elasticsearch/xpack/esql/ccq/MultiClusterSpecIT.java @@ -51,7 +51,7 @@ import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.ENABLE_LOOKUP_JOIN_ON_REMOTE; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.FORK_V9; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS; -import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS_V10; +import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.INLINESTATS_V11; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.JOIN_LOOKUP_V12; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.JOIN_PLANNING_V1; import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.METADATA_FIELDS_REMOTE_TEST; @@ -137,7 +137,7 @@ protected void shouldSkipTest(String testName) throws IOException { assumeTrue("Test " + testName + " is skipped on " + oldVersion, isEnabled(testName, instructions, oldVersion)); assumeFalse("INLINESTATS not yet supported in CCS", testCase.requiredCapabilities.contains(INLINESTATS.capabilityName())); assumeFalse("INLINESTATS not yet supported in CCS", testCase.requiredCapabilities.contains(JOIN_PLANNING_V1.capabilityName())); - assumeFalse("INLINESTATS not yet supported in CCS", testCase.requiredCapabilities.contains(INLINESTATS_V10.capabilityName())); + assumeFalse("INLINESTATS not yet supported in CCS", testCase.requiredCapabilities.contains(INLINESTATS_V11.capabilityName())); if (testCase.requiredCapabilities.contains(JOIN_LOOKUP_V12.capabilityName())) { assumeTrue( "LOOKUP JOIN not yet supported in CCS", diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec index 236c235f9d6f9..b9e29857e7985 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/inlinestats.csv-spec @@ -1,5 +1,5 @@ allFieldsReturned -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM hosts METADATA _index | INLINESTATS c = COUNT(*) BY host_group @@ -12,7 +12,7 @@ eth0 |epsilon gw instance|epsilon |[fe80::cae2:65ff:fece:feb9, ; maxOfInt -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 // tag::max-languages[] FROM employees | KEEP emp_no, languages @@ -34,7 +34,7 @@ emp_no:integer | languages:integer | max_lang:integer ; maxOfIntByKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender @@ -52,7 +52,7 @@ emp_no:integer | languages:integer | max_lang:integer | gender:keyword ; maxOfIntByKeywordLimit1Aggd -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender @@ -66,7 +66,7 @@ v:integer ; simpleAvg -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS a = AVG(salary) @@ -79,7 +79,7 @@ a:double ; maxOfLongByKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, avg_worked_seconds, gender @@ -94,7 +94,7 @@ emp_no:integer | avg_worked_seconds:long | max_avg_worked_seconds:long | gender: ; maxOfLong -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, avg_worked_seconds, gender @@ -107,7 +107,7 @@ emp_no:integer | avg_worked_seconds:long | gender:keyword | max_avg_worked_secon ; maxOfLongByCalculatedKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 // tag::longest-tenured-by-first[] FROM employees @@ -130,7 +130,7 @@ emp_no:integer | avg_worked_seconds:long | last_name:keyword | max_avg_worked_se ; maxOfLongByCalculatedNamedKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, avg_worked_seconds, last_name @@ -149,7 +149,7 @@ emp_no:integer | avg_worked_seconds:long | last_name:keyword | max_avg_worked_se ; maxOfLongByCalculatedDroppedKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_avg_worked_seconds = MAX(avg_worked_seconds) BY l = SUBSTRING(last_name, 0, 1) @@ -168,7 +168,7 @@ emp_no:integer | avg_worked_seconds:long | last_name:keyword | max_avg_worked_se ; maxOfLongByEvaledKeyword -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | EVAL l = SUBSTRING(last_name, 0, 1) @@ -188,7 +188,7 @@ emp_no:integer | avg_worked_seconds:long | max_avg_worked_seconds:long | l:keywo ; maxOfLongByInt -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, avg_worked_seconds, languages @@ -206,7 +206,7 @@ emp_no:integer | avg_worked_seconds:long | max_avg_worked_seconds:long | languag ; maxOfLongByIntDouble -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, avg_worked_seconds, languages, height @@ -224,7 +224,7 @@ emp_no:integer | avg_worked_seconds:long | max_avg_worked_seconds:long | languag ; two -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, avg_worked_seconds, gender @@ -248,7 +248,7 @@ emp_no:integer |avg_worked_seconds:long|avg_avg_worked_seconds:double|languages: ; three -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, avg_worked_seconds, gender @@ -276,7 +276,7 @@ emp_no:integer |avg_worked_seconds:long|avg_avg_worked_seconds:double|languages: // TODO: INLINESTATS unit test needed for this one // https://github.com/elastic/elasticsearch/issues/113727 pushDownSort_To_LeftSideOnly-Ignore -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | sort emp_no @@ -294,7 +294,7 @@ from employees ; byMultivaluedSimple -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 // tag::mv-group[] FROM airports @@ -312,7 +312,7 @@ abbrev:keyword | type:keyword | scalerank:integer | min_scalerank:integer ; byMultivaluedMvExpand -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 // tag::mv-expand[] FROM airports @@ -332,7 +332,7 @@ GWL |9 |4 |military ; byMvExpand -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 // tag::extreme-airports[] FROM airports @@ -361,7 +361,7 @@ FROM airports ; mvMinMvExpand -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | EVAL original_type = type @@ -384,7 +384,7 @@ ZAR |Zaria |POINT (7.7 11.0667) |Nigeria |POINT ( ; afterStats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | STATS count=COUNT(*) BY country @@ -407,7 +407,7 @@ count:long | country:keyword | avg:double ; afterWhere -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | WHERE country != "United States" @@ -425,7 +425,7 @@ abbrev:keyword | country:keyword | count:long ; afterLookup -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 required_capability: join_lookup_v12 FROM airports @@ -449,7 +449,7 @@ ZNZ |4 |German ; afterEnrich -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 required_capability: enrich_load FROM airports @@ -470,7 +470,7 @@ abbrev:keyword | city:keyword | "COUNT(*)":long | region:text ; beforeStats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | EVAL lat = ST_Y(location) @@ -483,7 +483,7 @@ northern:long | southern:long ; beforeKeepSort -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_salary = MAX(salary) by languages @@ -498,7 +498,7 @@ emp_no:integer | languages:integer | max_salary:integer ; beforeKeepWhere -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_salary = MAX(salary) by languages @@ -511,7 +511,7 @@ emp_no:integer | languages:integer | max_salary:integer ; beforeEnrich -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 required_capability: enrich_load FROM airports @@ -530,7 +530,7 @@ ACA |Acapulco de Juárez|385 |major |Acapulco de ; beforeAndAfterEnrich -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 required_capability: enrich_load FROM airports @@ -553,7 +553,7 @@ ALL |Albenga |499 |mid |1 ; shadowing -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW left = "left", client_ip = "172.21.0.5", env = "env", right = "right" | INLINESTATS env = VALUES(right) BY client_ip @@ -564,7 +564,7 @@ left | right | right | 172.21.0.5 ; shadowingMulti -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW left = "left", airport = "Zurich Airport ZRH", city = "Zürich", middle = "middle", region = "North-East Switzerland", right = "right" | INLINESTATS airport=VALUES(left), region=VALUES(left), city_boundary=VALUES(left) BY city @@ -575,7 +575,7 @@ left | middle | right | left | left ; shadowingSelf -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW city = "Raleigh" | INLINESTATS city = COUNT(city) @@ -586,7 +586,7 @@ city:long ; shadowingSelfBySelf -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW city = "Raleigh" | INLINESTATS city = COUNT(city) BY city @@ -598,7 +598,7 @@ Raleigh ; shadowingInternal -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW city = "Zürich" | INLINESTATS x = VALUES(city), x = VALUES(city) @@ -610,7 +610,7 @@ Zürich | Zürich ; multiInlinestatsWithRow -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 row x = 1 | inlinestats x = max(x) + min(x) @@ -624,7 +624,7 @@ row x = 1 ; ignoreUnusedEvaledValue_AndInlineStats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW x = 1 | INLINESTATS max(x) @@ -637,7 +637,7 @@ x:integer ; ignoreUnusedEvaledValue_AndInlineStats2 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW x = 1, z = 2 | INLINESTATS max(x) @@ -650,7 +650,7 @@ x:integer | z:integer ; ignoreUnusedEvaledValue_AndInlineStats3 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max(salary) @@ -665,7 +665,7 @@ from employees ; ignoreUnusedEvaledValue_AndInlineStats4 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max(salary), m = min(salary) by gender @@ -680,7 +680,7 @@ emp_no:integer ; ignoreUnusedEvaledValue_AndInlineStats5 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max(salary), m = min(salary) by gender @@ -695,7 +695,7 @@ emp_no:integer ; shadowEntireInlinestats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS x = avg(salary), y = min(salary) BY emp_no @@ -710,7 +710,7 @@ x:integer |y:integer |emp_no:integer ; byConstant -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages @@ -729,7 +729,7 @@ emp_no:integer | languages:integer | max_lang:integer | y:integer ; aggConstant -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no @@ -747,7 +747,7 @@ one:integer | emp_no:integer ; percentile -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, salary @@ -766,7 +766,7 @@ emp_no:integer | salary:integer | ninety_fifth_salary:double ; byTwoCalculated -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | WHERE abbrev IS NOT NULL @@ -786,7 +786,7 @@ abbrev:keyword | scalerank:integer | location:geo_point byTwoCalculatedSecondOverwrites required_capability: stats_alias_collision_warnings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | WHERE abbrev IS NOT NULL @@ -807,7 +807,7 @@ abbrev:keyword | scalerank:integer | location:geo_point byTwoCalculatedSecondOverwritesReferencingFirst required_capability: stats_alias_collision_warnings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | WHERE abbrev IS NOT NULL @@ -830,7 +830,7 @@ abbrev:keyword | scalerank:integer | location:geo_point groupShadowsAgg required_capability: stats_alias_collision_warnings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM airports | WHERE abbrev IS NOT NULL @@ -850,7 +850,7 @@ abbrev:keyword | scalerank:integer | location:geo_point ; groupShadowsField -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, salary, hire_date @@ -869,7 +869,7 @@ emp_no:integer | salary:integer | avg_salary:double | hire_date:datetime ; groupByExpression_And_ExistentField -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender | EVAL x = "ABC" @@ -887,7 +887,7 @@ emp_no:integer | languages:integer | x:keyword | max_lang:integer | y:keyword | ; groupByRenamedColumn -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender | INLINESTATS max_lang = MAX(languages) BY y = gender @@ -905,7 +905,7 @@ emp_no:integer | languages:integer | gender:keyword | max_lang:integer | y:keywo ; groupByMultipleRenamedColumns_AndOneExpression_Last -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, first_name @@ -928,7 +928,7 @@ emp_no:integer | languages:integer | gender:keyword|first_name:keyword|max_lang: ; groupByMultipleRenamedColumns_AndTwoExpressions -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, first_name @@ -951,7 +951,7 @@ emp_no:integer | languages:integer | gender:keyword|first_name:keyword|max_lang: ; groupByMultipleRenamedColumns_AndMultipleRenames -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, first_name @@ -975,7 +975,7 @@ emp_no:integer | languages:integer | gender:keyword| f:keyword |max_lang: ; groupByMultipleRenamedColumns_AndSameNameExpressionGroupingOverride -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, first_name @@ -999,7 +999,7 @@ emp_no:integer | languages:integer | gender:keyword|max_lang:integer| y:keyword ; twoAggregatesGroupedBy_AField_And_AnExpression -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, last_name @@ -1021,7 +1021,7 @@ emp_no:integer |languages:integer|last_name:keyword|max_lang:integer|min_lang:in ; groupByMultipleRenamedColumns_InversedOrder -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, still_hired, gender @@ -1039,7 +1039,7 @@ emp_no:integer |languages:integer|still_hired:boolean| gender:keyword|max_lang:i ; groupByMultipleRenamedColumns_InversedOrder_ComplexEval -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, still_hired, gender @@ -1058,7 +1058,7 @@ emp_no:integer |languages:integer|still_hired:boolean| gender:keyword|multilingu ; groupByMultipleRenamedColumns_AndComplexEval -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, still_hired, gender @@ -1077,7 +1077,7 @@ emp_no:integer |languages:integer|still_hired:boolean| gender:keyword|multilingu ; groupByMultipleRenamedColumns_AndConstantValue -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, first_name @@ -1101,7 +1101,7 @@ emp_no:integer |languages:integer|gender:keyword |first_name:keyword | x:keyw ; groupByRenamedExpression -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP emp_no, languages, gender, last_name @@ -1123,7 +1123,7 @@ emp_no:integer |languages:integer|last_name:keyword|max_lang:integer|min_lang:in ; doubleFilterOnLeftAndRight_InlineStats_Sides -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_salary = MAX(salary), min_salary = MIN(salary) by languages @@ -1144,7 +1144,7 @@ emp_no:integer |languages:integer|salary:integer |max_salary:integer|min_salary: ; filterOnInlineStatsAggs -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_salary = MAX(salary), min_salary = MIN(salary) by languages @@ -1163,7 +1163,7 @@ emp_no:integer |languages:integer|salary:integer |max_salary:integer|min_salary: ; filterOnInlineStatsAggsValues_And_Groupings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS max_salary = MAX(salary), min_salary = MIN(salary) by languages @@ -1182,7 +1182,7 @@ emp_no:integer |languages:integer|salary:integer |max_salary:integer|min_salary: ; inlineStatsOverrideEVALed_FieldWithSameName -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM hosts METADATA _index | EVAL x = ip1 @@ -1196,7 +1196,7 @@ beta k8s server |beta |127.0.0.1 |hosts |127.0.0.2|2 ; doubleShadowing -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS salary = min(salary) BY gender @@ -1215,7 +1215,7 @@ salary:integer |gender:keyword ; doubleShadowing_WithIntertwinedFilters -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | WHERE salary > 30000 @@ -1240,7 +1240,7 @@ salary:integer |gender:keyword ; shadowingAggregateByNextGrouping -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP gender, languages, emp_no, salary @@ -1257,7 +1257,7 @@ emp_no:integer |salary:integer |languages:integer|avg(salary):double|gender:long ; doubleShadowingWithEval -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval salary = salary/100 @@ -1277,7 +1277,7 @@ salary:integer|gender:keyword ; doubleShadowingWithDoubleStats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | stats salary=min(salary) by gender @@ -1294,7 +1294,7 @@ M |25324 ; renamingGroupingWithItself -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | EVAL x = gender @@ -1313,7 +1313,7 @@ salary:integer |x:keyword|gender:keyword |min_sl:integer |emp_no:integer ; overridingGroupings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS min_sl = MIN(salary) BY x = gender, x = languages @@ -1332,7 +1332,7 @@ salary:integer |x:integer |gender:keyword |min_sl:integer |emp_no:integer ; overridingExpressionGroupings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | INLINESTATS min_sl = MIN(salary) BY x = TO_LOWER(gender), x = CONCAT(gender, gender) @@ -1351,7 +1351,7 @@ salary:integer |x:keyword |gender:keyword |min_sl:integer |emp_no:integer ; reusingEvalExpressions_UsedInGroupings -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | KEEP salary, gender, emp_no @@ -1370,7 +1370,7 @@ salary:integer |gender:keyword |emp_no:integer |min_sl:integer | x:keyword ; statsBeforeInlinestatsWithTopAndBucket1 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM books | STATS avg_rating = AVG(ratings) BY decade = BUCKET(year, 10) @@ -1390,7 +1390,7 @@ avg_rating:double | decade:double | decades:double ; statsBeforeInlinestatsWithTopAndBucket2 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM sample_data | STATS total_duration = SUM(event_duration) BY day = BUCKET(@timestamp, 1 HOUR) @@ -1406,7 +1406,7 @@ total_duration:long | day:date | days:date evalBeforeInlinestatsAndKeepAfter1 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | WHERE still_hired == false @@ -1426,7 +1426,7 @@ emp_no:integer |still_hired:boolean|totalK:long|count:long ; evalBeforeInlinestatsAndKeepAfter2 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | EVAL salaryK = salary/1000 @@ -1446,7 +1446,7 @@ emp_no:integer |still_hired:boolean|total:long|count:long ; evalBeforeInlinestatsAndKeepAfter3 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | EVAL salaryK = salary/1000 @@ -1465,7 +1465,7 @@ emp_no:integer |still_hired:boolean|total:long ; evalBeforeInlinestatsAndKeepAfter4 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | EVAL salaryK = salary/1000 @@ -1484,7 +1484,7 @@ emp_no:integer |still_hired:boolean|count:long ; evalBeforeInlinestatsAndKeepAfter5 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 ROW salary = 12300, emp_no = 5, gender = "F" | EVAL salaryK = salary/1000 @@ -1500,7 +1500,7 @@ emp_no:integer /////////////////////////// doubleFilterOnInlineStats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | keep salary, gender @@ -1526,7 +1526,7 @@ salary:integer | max1:integer | max2:integer | max3:integer | gender:keyword ; inlinestatsWithFiltering -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary), max_f = max(salary) where salary < 50000, max_a = max(salary) where salary > 100, min = min(salary), min_f = min(salary) where salary > 50000, min_a = min(salary) where salary > 100 @@ -1542,7 +1542,7 @@ max:integer |max_f:integer |max_a:integer | min:integer | min_f:integer | min_a: ; inlinestatsWithEverythingFiltered -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary), max_a = max(salary) where salary < 100, min = min(salary), min_a = min(salary) where salary > 99999 @@ -1560,7 +1560,7 @@ max:integer |max_a:integer|min:integer | min_a:integer | emp_no:integer|salary:i ; inlinestatsWithNullFilter -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary), max_a = max(salary) where null, min = min(salary), min_a = min(salary) where to_string(null) == "abc" @@ -1576,7 +1576,7 @@ max:integer |max_a:integer|min:integer | min_a:integer | emp_no:integer ; inlinestatsWithAllFiltersFalse -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(height.float) where false, min = min(height.float) where to_string(null) == "abc", @@ -1594,7 +1594,7 @@ emp_no:integer|salary:integer| max:double |min:double |count:long |count_distinc ; inlinestatsWithAllFiltersFalse_GroupByOneField -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(height.float) where false, min = min(height.float) where to_string(null) == "abc", @@ -1614,7 +1614,7 @@ from employees ; inlinestatsWithAllFiltersFalse_GroupByTwoFields -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(height.float) where false, min = min(height.float) where to_string(null) == "abc", @@ -1634,7 +1634,7 @@ from employees ; prunedInlinestatsFollowedByInlinestats_GroupByOneFieldEach_DifferentFields -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(my_length) where false, @@ -1652,7 +1652,7 @@ from employees ; prunedInlinestatsFollowedByInlinestats_GroupByOneFieldEach_SameFields -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(my_length) where false, @@ -1671,7 +1671,7 @@ from employees prunedInlinestatsFollowedByInlinestats_GroupByOneFieldOnSecondInlinestats-Ignore // values doesn't end up as null -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(my_length) where false, @@ -1689,7 +1689,7 @@ from employees ; partial_PrunedInlinestatsFollowedByInlinestats_GroupByOneFieldOnFirstInlinestats -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(is_rehired) where true, @@ -1715,7 +1715,7 @@ from employees partial_PrunedInlinestatsFollowedByInlinestats_GroupByOneFieldOnFirstInlinestats2 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(is_rehired) where true, @@ -1742,7 +1742,7 @@ from employees inlinestatsWithExpressionsAllFiltersFalse -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | keep height.f*, emp_no | sort emp_no desc @@ -1760,7 +1760,7 @@ from employees ; inlinestatsWithFalseFilterAndGroup -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(height.float + 1) where null, count = count(height.float) + 2 where false @@ -1778,7 +1778,7 @@ from employees ; inlinestatsWithFalseFiltersAndGroups -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count_distinct = count_distinct(height.float + 1) where null, @@ -1804,7 +1804,7 @@ from employees ; inlinestatsWithFalseFiltersAndGroups_DropEvaledValue -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count_distinct = count_distinct(height.float + 1) where null, @@ -1831,7 +1831,7 @@ from employees ; inlinestatsWithMixedFiltersAndGroup -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(my_length) where false, @@ -1851,7 +1851,7 @@ null |[0, 0, 0, 0] |[Berni, Chirstian, Amabile, Berni, Bojan, Chir prunedInlinestatsFollowedByinlinestats-Ignore // values doesn't end up as null -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval my_length = length(concat(first_name, null)) | inlinestats count = count(my_length) where false, @@ -1874,7 +1874,7 @@ inlinestatsWithFalseFiltersFromRow // null |2 // null |3 // null |4 -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 row x = null, a = 1, b = [2,3,4] | inlinestats c=max(a) where x by b @@ -1885,7 +1885,7 @@ null |1 |null |[2, 3, 4] ; inlinestatsWithBasicExpressionFiltered -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary), max_f = max(salary) where salary < 50000, min = min(salary), min_f = min(salary) where salary > 50000, @@ -1901,7 +1901,7 @@ from employees ; inlinestatsWithExpressionOverFilters -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary), max_f = max(salary) where salary < 50000, min = min(salary), min_f = min(salary) where salary > 50000, @@ -1920,7 +1920,7 @@ from employees inlinestatsWithExpressionOfExpressionsOverFilters -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats max = max(salary + 1), max_f = max(salary + 2) where salary < 50000, min = min(salary - 1), min_f = min(salary - 2) where salary > 50000, @@ -1938,7 +1938,7 @@ from employees ; inlinestatsWithSubstitutedExpressionOverFilters -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats sum = sum(salary), s_l = sum(salary) where salary < 50000, s_u = sum(salary) where salary > 50000, count = count(salary), c_l = count(salary) where salary < 50000, c_u = count(salary) where salary > 50000, @@ -1956,7 +1956,7 @@ from employees inlinestatsWithFilterAndGroupBy -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | keep height, gender, is_rehired, emp_no | inlinestats m = max(height), m_f = max(height + 1) where gender == "M" OR is_rehired is null BY gender, is_rehired @@ -1980,7 +1980,7 @@ from employees inlinestatsWithFilterOnGroupBy -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats m_f = max(height) where gender == "M" BY gender | sort emp_no @@ -2002,7 +2002,7 @@ null |null ; inlinestatsWithGroupByLiteral -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats m = max(languages) by salary = 2 | sort salary @@ -2018,7 +2018,7 @@ from employees inlinestatsWithFilterOnSameColumn -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats m = max(languages), m_f = max(languages) where salary > 50000 by salary = 2 | sort salary @@ -2033,7 +2033,7 @@ from employees ; inlinestatsWithFilteringAndGrouping -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c = count(), c_f = count(languages) where l > 1, m_f = max(height) where salary > 50000 @@ -2058,7 +2058,7 @@ from employees multiinlinestatsWithFiltering -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c = count(), c_f = count(languages) where l > 1, m_f = max(height) where salary > 50000 @@ -2085,7 +2085,7 @@ from employees simpleCountOnFieldWithFilteringAndNoGrouping -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c1 = count(emp_no) where emp_no < 10042 | keep emp_no, c1 @@ -2100,7 +2100,7 @@ emp_no:integer | c1:long ; simpleCountOnFieldWithFilteringOnDifferentFieldAndNoGrouping -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c1 = count(hire_date) where emp_no < 10042 | keep emp_no, c1 @@ -2115,7 +2115,7 @@ emp_no:integer | c1:long ; simpleCountOnStarWithFilteringAndNoGrouping -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c1 = count(*) where emp_no < 10042 | keep emp_no, c1 @@ -2130,7 +2130,7 @@ emp_no:integer | c1:long ; simpleCountWithFilteringAndNoGroupingOnFieldWithNulls -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c1 = count(birth_date) where emp_no <= 10050 | keep emp_no, c1 @@ -2146,7 +2146,7 @@ emp_no:integer | c1:long simpleCountWithFilteringAndNoGroupingOnFieldWithMultivalues -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | inlinestats c1 = count(job_positions) where emp_no <= 10003 | keep emp_no, c1 @@ -2161,7 +2161,7 @@ from employees ; commonFilterExtractionWithAliasing -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval eno = emp_no | drop emp_no @@ -2179,7 +2179,7 @@ from employees ; commonFilterExtractionWithAliasAndOriginal -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval eno = emp_no | inlinestats min_sal = min(salary) where eno <= 10010, @@ -2197,7 +2197,7 @@ from employees commonFilterExtractionWithAliasAndOriginalNeedingNormalization -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval eno = emp_no | inlinestats min_sal = min(salary) where eno <= 10010, @@ -2217,7 +2217,7 @@ from employees ; commonFilterExtractionWithAliasAndOriginalNeedingNormalizationAndSimplification -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | eval eno = emp_no | inlinestats min_sal = min(salary) where eno <= 10010, @@ -2237,7 +2237,7 @@ from employees ; filterIsAlwaysTrue -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats max = max(salary) WHERE salary > 0 | keep max, salary, emp_no @@ -2252,7 +2252,7 @@ FROM employees ; filterIsAlwaysFalse -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats max = max(salary) WHERE first_name == "" | sort emp_no @@ -2275,7 +2275,7 @@ null |Duangkaew filterSometimesMatches -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats max = max(salary) WHERE first_name IS NULL | sort emp_no @@ -2297,7 +2297,7 @@ FROM employees ; groupingFilterIsAlwaysTrue -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | MV_EXPAND job_positions | inlinestats max = max(salary) WHERE salary > 0 BY job_positions = SUBSTRING(job_positions, 1, 1) @@ -2315,7 +2315,7 @@ FROM employees groupingFilterIsAlwaysFalse -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | MV_EXPAND job_positions | inlinestats max = max(salary) WHERE first_name == "" BY job_positions = SUBSTRING(job_positions, 1, 1) @@ -2333,7 +2333,7 @@ null |48942 |Patricio |A |10012 groupingFilterSometimesMatches -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | MV_EXPAND job_positions | inlinestats max = max(salary) WHERE first_name IS NULL BY job_positions = SUBSTRING(job_positions, 1, 1) @@ -2350,7 +2350,7 @@ FROM employees ; groupingByOrdinalsFilterIsAlwaysTrue -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats max = max(salary) WHERE salary > 0 BY job_positions | SORT job_positions ASC, salary DESC @@ -2366,7 +2366,7 @@ FROM employees ; groupingByOrdinalsFilterIsAlwaysFalse -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats max = max(salary) WHERE first_name == "" BY job_positions @@ -2383,7 +2383,7 @@ Mary |31120 |10011 |[Architect, Reporting Analyst, S ; groupingByOrdinalsFilterSometimesMatches -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | keep salary, first_name, job_positions, emp_no @@ -2400,7 +2400,7 @@ FROM employees ; stdDevFilter -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 FROM employees | inlinestats greater_than = STD_DEV(salary_change) WHERE languages > 3 , less_than = STD_DEV(salary_change) WHERE languages <= 3 @@ -2425,7 +2425,7 @@ FROM employees ; twoConsecutiveInlinestatsWithFalseFilters -required_capability: inlinestats_v10 +required_capability: inlinestats_v11 from employees | keep emp_no | sort emp_no diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 4672dc4500922..911c5ed641da0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -972,7 +972,7 @@ public enum Cap { * Fixes a series of issues with inlinestats which had an incomplete implementation after lookup and inlinestats * were refactored. */ - INLINESTATS_V10(EsqlPlugin.INLINESTATS_FEATURE_FLAG), + INLINESTATS_V11(EsqlPlugin.INLINESTATS_FEATURE_FLAG), /** * Support partial_results diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index 8753ff28b9938..8595dab76ebe9 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -4241,7 +4241,7 @@ public void testGroupingOverridesInStats() { } public void testGroupingOverridesInInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); verifyUnsupported(""" from test | inlinestats MIN(salary) BY x = languages, x = x + 1 diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java index b9a469edae907..662ca51ab564d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java @@ -83,7 +83,7 @@ public static void init() { * \_StubRelation[[emp_no{f}#11, languages{f}#14, gender{f}#13, y{r}#10]] */ public void testGroupingAliasingMoved_To_LeftSideOfJoin() { - assumeTrue("Requires INLINESTATS", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("Requires INLINESTATS", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); var plan = plan(""" from test | keep emp_no, languages, gender @@ -126,7 +126,7 @@ public void testGroupingAliasingMoved_To_LeftSideOfJoin() { * {r}#21]] */ public void testGroupingAliasingMoved_To_LeftSideOfJoin_WithExpression() { - assumeTrue("Requires INLINESTATS", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("Requires INLINESTATS", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); var plan = plan(""" from test | keep emp_no, languages, gender, last_name, first_name diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/FieldNameUtilsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/FieldNameUtilsTests.java index 734d14337175a..10cde6f9297ec 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/FieldNameUtilsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/FieldNameUtilsTests.java @@ -34,7 +34,7 @@ public void testBasicFromCommand() { } public void testBasicFromCommandWithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames("from test | inlinestats max(salary) by gender", ALL_FIELDS); } @@ -43,7 +43,7 @@ public void testBasicFromCommandWithMetadata() { } public void testBasicFromCommandWithMetadata_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames("from test metadata _index, _id, _version | inlinestats max(salary)", ALL_FIELDS); } @@ -320,7 +320,7 @@ public void testLimitZero() { } public void testLimitZero_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" FROM employees | INLINESTATS COUNT(*), MAX(salary) BY gender @@ -335,7 +335,7 @@ public void testDocsDropHeight() { } public void testDocsDropHeight_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" FROM employees | DROP height @@ -351,7 +351,7 @@ public void testDocsDropHeightWithWildcard() { } public void testDocsDropHeightWithWildcard_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" FROM employees | INLINESTATS MAX(salary) BY gender @@ -518,7 +518,7 @@ public void testSortWithLimitOne_DropHeight() { } public void testSortWithLimitOne_DropHeight_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames("from employees | inlinestats avg(salary) by languages | sort languages | limit 1 | drop height*", ALL_FIELDS); } @@ -818,7 +818,7 @@ public void testFilterById() { } public void testFilterById_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames("FROM apps metadata _id | INLINESTATS max(rate) | WHERE _id == \"4\"", ALL_FIELDS); } @@ -1289,7 +1289,7 @@ public void testProjectDropPattern() { } public void testProjectDropPattern_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | inlinestats max(foo) by bar @@ -1372,7 +1372,7 @@ public void testCountAllAndOtherStatGrouped() { } public void testCountAllAndOtherStatGrouped_WithInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | inlinestats c = count(*), min = min(emp_no) by languages @@ -1411,7 +1411,7 @@ public void testCountAllWithEval() { } public void testCountAllWithEval_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | rename languages as l @@ -1424,7 +1424,7 @@ public void testCountAllWithEval_AndInlinestats() { } public void testKeepAfterEval_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | rename languages as l @@ -1437,7 +1437,7 @@ public void testKeepAfterEval_AndInlinestats() { } public void testKeepBeforeEval_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | rename languages as l @@ -1450,7 +1450,7 @@ public void testKeepBeforeEval_AndInlinestats() { } public void testStatsBeforeEval_AndInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | rename languages as l @@ -1462,7 +1462,7 @@ public void testStatsBeforeEval_AndInlinestats() { } public void testStatsBeforeInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | stats min = min(salary) by languages @@ -1471,7 +1471,7 @@ public void testStatsBeforeInlinestats() { } public void testKeepBeforeInlinestats() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertFieldNames(""" from test | keep languages, salary @@ -2845,7 +2845,7 @@ public void testForkAfterMvExpand() { } public void testForkBeforeInlineStatsIgnore() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertTrue("FORK required", EsqlCapabilities.Cap.FORK_V9.isEnabled()); assertFieldNames(""" FROM employees @@ -2858,7 +2858,7 @@ public void testForkBeforeInlineStatsIgnore() { } public void testForkBranchWithInlineStatsIgnore() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertTrue("FORK required", EsqlCapabilities.Cap.FORK_V9.isEnabled()); assertFieldNames(""" FROM employees @@ -2872,7 +2872,7 @@ public void testForkBranchWithInlineStatsIgnore() { } public void testForkAfterInlineStatsIgnore() { - assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V10.isEnabled()); + assumeTrue("INLINESTATS required", EsqlCapabilities.Cap.INLINESTATS_V11.isEnabled()); assertTrue("FORK required", EsqlCapabilities.Cap.FORK_V9.isEnabled()); assertFieldNames(""" FROM employees From 98140a304eb4ad01e54b964047428383dac03373 Mon Sep 17 00:00:00 2001 From: Bogdan Pintea Date: Wed, 27 Aug 2025 23:48:34 +0200 Subject: [PATCH 3/4] Further tests adjustments --- .../optimizer/LogicalPlanOptimizerTests.java | 56 ++++++++----------- .../ReplaceStatsFilteredAggWithEvalTests.java | 24 +++----- 2 files changed, 31 insertions(+), 49 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index 96e66faf871c6..cc0788e8444eb 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -1044,10 +1044,12 @@ public void testPushdownLimitsPastLeftJoin() { var optimizedPlan = rule.apply(limit, logicalOptimizerCtx); - assertEquals( - new Limit(limit.source(), limit.limit(), join.replaceChildren(limit.replaceChild(join.left()), join.right()), true), - optimizedPlan - ); + var expectedPlan = join instanceof InlineJoin + ? new Limit(limit.source(), limit.limit(), join, false) + : new Limit(limit.source(), limit.limit(), join.replaceChildren(limit.replaceChild(join.left()), join.right()), true); + + + assertEquals(expectedPlan, optimizedPlan); var optimizedTwice = rule.apply(optimizedPlan, logicalOptimizerCtx); // We mustn't create the limit after the JOIN multiple times when the rule is applied multiple times, that'd lead to infinite loops. @@ -5714,17 +5716,14 @@ public void testReplaceSortByExpressionsWithStats() { as(aggregate.child(), EsRelation.class); } - /** - *
{@code
-     * Limit[1000[INTEGER],true]
+    /*
+     * Limit[1000[INTEGER],false]
      * \_InlineJoin[LEFT,[emp_no % 2{r}#6],[emp_no % 2{r}#6],[emp_no % 2{r}#6]]
      *   |_Eval[[emp_no{f}#7 % 2[INTEGER] AS emp_no % 2#6]]
-     *   | \_Limit[1000[INTEGER],false]  <-- TODO: this needs to go
-     *   |   \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..]
+     *   | \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..]
      *   \_Aggregate[[emp_no % 2{r}#6],[COUNT(salary{f}#12,true[BOOLEAN]) AS c#4, emp_no % 2{r}#6]]
      *     \_StubRelation[[_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, gender{f}#9, hire_date{f}#14, job{f}#15, job.raw{f}#16, lang
      *          uages{f}#10, last_name{f}#11, long_noidx{f}#17, salary{f}#12, emp_no % 2{r}#6]]
-     * }
*/ public void testInlinestatsNestedExpressionsInGroups() { var query = """ @@ -5739,7 +5738,7 @@ public void testInlinestatsNestedExpressionsInGroups() { var inline = as(limit.child(), InlineJoin.class); var eval = as(inline.left(), Eval.class); assertThat(Expressions.names(eval.fields()), is(List.of("emp_no % 2"))); - limit = asLimit(eval.child(), 1000, false); + var relation = as(eval.child(), EsRelation.class); var agg = as(inline.right(), Aggregate.class); var groupings = agg.groupings(); var ref = as(groupings.get(0), ReferenceAttribute.class); @@ -5811,17 +5810,14 @@ public void testDoubleInlinestatsGetsPrunedEntirely() { var relation = as(topN.child(), EsRelation.class); } - /** - *
{@code
+    /*
      * Project[[emp_no{f}#15 AS x#11, a{r}#7, emp_no{f}#15]]
-     * \_Limit[1[INTEGER],true]
+     * \_Limit[1[INTEGER],false]
      *   \_InlineJoin[LEFT,[emp_no{f}#15],[emp_no{f}#15],[emp_no{r}#15]]
-     *     |_Limit[1[INTEGER],false]  <-- TODO: this needs to go
-     *     | \_EsRelation[test][_meta_field{f}#21, emp_no{f}#15, first_name{f}#16, ..]
+     *     |_EsRelation[test][_meta_field{f}#21, emp_no{f}#15, first_name{f}#16, ..]
      *     \_Aggregate[[emp_no{f}#15],[COUNTDISTINCT(languages{f}#18,true[BOOLEAN]) AS a#7, emp_no{f}#15]]
      *       \_StubRelation[[_meta_field{f}#21, emp_no{f}#15, first_name{f}#16, gender{f}#17, hire_date{f}#22, job{f}#23, job.raw{f}#24, l
      *          anguages{f}#18, last_name{f}#19, long_noidx{f}#25, salary{f}#20]]
-     * }
*/ public void testInlinestatsGetsPrunedPartially() { var query = """ @@ -5838,13 +5834,11 @@ public void testInlinestatsGetsPrunedPartially() { var project = as(plan, Project.class); assertThat(Expressions.names(project.projections()), is(List.of("x", "a", "emp_no"))); - var upperLimit = asLimit(project.child(), 1, true); + var upperLimit = asLimit(project.child(), 1, false); var inlineJoin = as(upperLimit.child(), InlineJoin.class); assertThat(Expressions.names(inlineJoin.config().matchFields()), is(List.of("emp_no"))); // Left - var limit = as(inlineJoin.left(), Limit.class); // TODO: this needs to go - assertThat(limit.limit().fold(FoldContext.small()), equalTo(1)); - var relation = as(limit.child(), EsRelation.class); + var relation = as(inlineJoin.left(), EsRelation.class); // Right var agg = as(inlineJoin.right(), Aggregate.class); assertMap(Expressions.names(agg.output()), is(List.of("a", "emp_no"))); @@ -5869,13 +5863,11 @@ public void testTrippleInlinestatsGetsPrunedPartially() { var project = as(plan, Project.class); assertThat(Expressions.names(project.projections()), is(List.of("x", "a", "emp_no"))); - var upperLimit = asLimit(project.child(), 1, true); + var upperLimit = asLimit(project.child(), 1, false); var inlineJoin = as(upperLimit.child(), InlineJoin.class); assertThat(Expressions.names(inlineJoin.config().matchFields()), is(List.of("emp_no"))); // Left - var limit = as(inlineJoin.left(), Limit.class); - assertThat(limit.limit().fold(FoldContext.small()), equalTo(1)); - var relation = as(limit.child(), EsRelation.class); + var relation = as(inlineJoin.left(), EsRelation.class); // Right var agg = as(inlineJoin.right(), Aggregate.class); assertMap(Expressions.names(agg.output()), is(List.of("a", "emp_no"))); @@ -5926,20 +5918,17 @@ public void testInlinestatsWithLookupJoin() { assertThat(right.concreteIndices(), is(Set.of("languages_lookup"))); } - /** - *
{@code
+    /*
      * EsqlProject[[avg{r}#4, emp_no{f}#9, first_name{f}#10]]
-     * \_Limit[10[INTEGER],true]
+     * \_Limit[10[INTEGER],false]
      *   \_InlineJoin[LEFT,[emp_no{f}#9],[emp_no{f}#9],[emp_no{r}#9]]
-     *     |_Limit[10[INTEGER],false]  <-- TODO: this needs to go
-     *     | \_EsRelation[test][_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, g..]
+     *     |_EsRelation[test][_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, g..]
      *     \_Project[[avg{r}#4, emp_no{f}#9]]
      *       \_Eval[[$$SUM$avg$0{r$}#20 / $$COUNT$avg$1{r$}#21 AS avg#4]]
      *         \_Aggregate[[emp_no{f}#9],[SUM(salary{f}#14,true[BOOLEAN]) AS $$SUM$avg$0#20, COUNT(salary{f}#14,true[BOOLEAN]) AS $$COUNT$
      *              avg$1#21, emp_no{f}#9]]
      *           \_StubRelation[[_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, gender{f}#11, hire_date{f}#16, job{f}#17, job.raw{f}#18,
      *              languages{f}#12, last_name{f}#13, long_noidx{f}#19, salary{f}#14]]
-     * }
*/ public void testInlinestatsWithAvg() { var query = """ @@ -5955,12 +5944,11 @@ public void testInlinestatsWithAvg() { var esqlProject = as(plan, EsqlProject.class); assertThat(Expressions.names(esqlProject.projections()), is(List.of("avg", "emp_no", "first_name"))); - var upperLimit = asLimit(esqlProject.child(), 10, true); + var upperLimit = asLimit(esqlProject.child(), 10, false); var inlineJoin = as(upperLimit.child(), InlineJoin.class); assertThat(Expressions.names(inlineJoin.config().matchFields()), is(List.of("emp_no"))); // Left - var limit = asLimit(inlineJoin.left(), 10, false); // TODO: this needs to go - var relation = as(limit.child(), EsRelation.class); + var relation = as(inlineJoin.left(), EsRelation.class); // Right var project = as(inlineJoin.right(), Project.class); assertThat(Expressions.names(project.projections()), contains("avg", "emp_no")); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStatsFilteredAggWithEvalTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStatsFilteredAggWithEvalTests.java index 464c12a81f97d..f844e39a76df3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStatsFilteredAggWithEvalTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/ReplaceStatsFilteredAggWithEvalTests.java @@ -463,12 +463,11 @@ public void testReplaceInlinestatsFilteredAggWithEvalSingleAggWithExpression() { as(limit.child(), EsRelation.class); } - /** - * Limit[1000[INTEGER],true] + /* + * Limit[1000[INTEGER],false] * \_InlineJoin[LEFT,[emp_no{f}#9],[emp_no{f}#9],[emp_no{r}#9]] * |_EsqlProject[[salary{f}#14, emp_no{f}#9]] - * | \_Limit[1000[INTEGER],false] - * | \_EsRelation[test][_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, g..] + * | \_EsRelation[test][_meta_field{f}#15, emp_no{f}#9, first_name{f}#10, g..] * \_Project[[sum(salary) 1 where false{r}#5, sum(salary) 2{r}#7, emp_no{f}#9]] * \_Eval[[null[LONG] AS sum(salary) 1 where false#5, $$SUM$sum(salary)_ _2$1{r$}#21 2[INTEGER] AS sum(salary) 2#7]] * \_Aggregate[[emp_no{f}#9],[SUM(salary{f}#14,true[BOOLEAN],compensated[KEYWORD]) AS $$SUM$sum(salary)_ _2$1#21, emp_no{f}#9]] @@ -487,8 +486,7 @@ public void testReplaceInlinestatsFilteredAggWithEvalMixedFilterAndNoFilter() { var ij = as(limit.child(), InlineJoin.class); var left = as(ij.left(), EsqlProject.class); assertThat(Expressions.names(left.projections()), contains("salary", "emp_no")); - limit = as(left.child(), Limit.class); - as(limit.child(), EsRelation.class); + var relation = as(left.child(), EsRelation.class); var right = as(ij.right(), Project.class); assertMap( Expressions.names(right.projections()).stream().map(Object::toString).toList(), @@ -598,12 +596,11 @@ public void testReplaceInlinestatsFilteredAggWithEvalNotTrue() { as(limit.child(), EsRelation.class); } - /** + /* * Limit[1000[INTEGER],true] * \_InlineJoin[LEFT,[],[],[]] * |_EsqlProject[[emp_no{f}#8, salary{f}#13, gender{f}#10]] - * | \_Limit[1000[INTEGER],false] - * | \_EsRelation[test][_meta_field{f}#14, emp_no{f}#8, first_name{f}#9, ge..] + * | \_EsRelation[test][_meta_field{f}#14, emp_no{f}#8, first_name{f}#9, ge..] * \_Aggregate[[],[COUNT(salary{f}#13,true[BOOLEAN]) AS m1#7]] * \_StubRelation[[emp_no{f}#8, salary{f}#13, gender{f}#10]] */ @@ -618,8 +615,7 @@ public void testReplaceInlinestatsFilteredAggWithEvalNotFalse() { var left = as(ij.left(), EsqlProject.class); assertThat(Expressions.names(left.projections()), contains("emp_no", "salary", "gender")); - var leftLimit = as(left.child(), Limit.class); - as(leftLimit.child(), EsRelation.class); + var relation = as(left.child(), EsRelation.class); var right = as(ij.right(), Aggregate.class); assertThat(Expressions.names(right.aggregates()), contains("m1")); @@ -687,8 +683,7 @@ public void testReplaceInlinestatsFilteredAggWithEvalCountDistinctInExpression() * Limit[1000[INTEGER],true] * \_InlineJoin[LEFT,[emp_no{f}#17],[emp_no{f}#17],[emp_no{r}#17]] * |_EsqlProject[[emp_no{f}#17, salary{f}#22]] - * | \_Limit[1000[INTEGER],false] - * | \_EsRelation[test][_meta_field{f}#23, emp_no{f}#17, first_name{f}#18, ..] + * | \_EsRelation[test][_meta_field{f}#23, emp_no{f}#17, first_name{f}#18, ..] * \_Project[[max{r}#6, max_a{r}#9, min{r}#12, min_a{r}#15, emp_no{f}#17]] * \_Eval[[null[INTEGER] AS max_a#9, null[INTEGER] AS min_a#15]] * \_Aggregate[[emp_no{f}#17],[MAX(salary{f}#22,true[BOOLEAN]) AS max#6, MIN(salary{f}#22,true[BOOLEAN]) AS min#12, emp_no{f}#17]] @@ -708,8 +703,7 @@ public void testReplaceInlinestatsFilteredAggWithEvalSameAggWithAndWithoutFilter var left = as(ij.left(), EsqlProject.class); assertThat(Expressions.names(left.projections()), contains("emp_no", "salary")); - var leftLimit = as(left.child(), Limit.class); - as(leftLimit.child(), EsRelation.class); + var relation = as(left.child(), EsRelation.class); var right = as(ij.right(), Project.class); assertThat(Expressions.names(right.projections()), contains("max", "max_a", "min", "min_a", "emp_no")); From f63f390bef9c760a24dcc568055782244736ca18 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 27 Aug 2025 22:07:51 +0000 Subject: [PATCH 4/4] [CI] Auto commit changes from spotless --- .../xpack/esql/optimizer/LogicalPlanOptimizerTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index cc0788e8444eb..ae8e6bb0cb16e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -1048,7 +1048,6 @@ public void testPushdownLimitsPastLeftJoin() { ? new Limit(limit.source(), limit.limit(), join, false) : new Limit(limit.source(), limit.limit(), join.replaceChildren(limit.replaceChild(join.left()), join.right()), true); - assertEquals(expectedPlan, optimizedPlan); var optimizedTwice = rule.apply(optimizedPlan, logicalOptimizerCtx);